JoshuaKGoldberg / package.json-validator

Tools to validate package.json files
MIT License
107 stars 26 forks source link

🚀 Feature: Recommend `main` and `exports` #69

Open brettz9 opened 4 years ago

brettz9 commented 4 years ago

Per https://nodejs.org/api/esm.html#esm_main_entry_point_export

To set the main entry point for a package, it is advisable to define both "exports" and "main" in the package’s package.json file:

{ "main": "./main.js", "exports": "./main.js" }

The benefit of doing this is that when using the "exports" field all subpaths of the package will no longer be available to importers under require('pkg/subpath.js'), and instead they will get a new error, ERR_PACKAGE_PATH_NOT_EXPORTED.

This encapsulation of exports provides more reliable guarantees about package interfaces for tools and when handling semver upgrades for a package. It is not a strong encapsulation since a direct require of any absolute subpath of the package such as require('/path/to/node_modules/pkg/subpath.js') will still load subpath.js.

Also the order within exports (and the order within exports subpaths, e.g., {exports: {"./feature": {browser: "./feature-browser.js", default: "./feature.js"}} and within nested conditions, e.g., {"exports": {"import": {"node": "./feature-node.mjs"}}}) could be enforced per https://nodejs.org/api/esm.html#esm_conditional_exports :

"node" - matched for any Node.js environment. Can be a CommonJS or ES module file. This condition should always come after "import" or "require". "default" - the generic fallback that will always match. Can be a CommonJS or ES module file. This condition should always come last.

LinusU commented 4 years ago

We should probably note that it's in most cases a breaking change to add exports:

https://medium.com/javascript-in-plain-english/is-promise-post-mortem-cab807f18dcc