@@ -183,25 +183,75 @@ versions of Node.js, but its capabilities are limited: it only defines the main
183183entry point of the package.
184184
185185The ` "exports" ` field provides an alternative to ` "main" ` where the package
186- main entry point can be defined while also encapsulating the package, preventing
187- any other entry points besides those defined in ` "exports" ` . If package entry
188- points are defined in both ` "main" ` and ` "exports" ` , the latter takes precedence
189- in versions of Node.js that support ` "exports" ` . [ Conditional Exports] [ ] can
190- also be used within ` "exports" ` to define different package entry points per
191- environment, including whether the package is referenced via ` require ` or via
192- ` import ` .
186+ main entry point can be defined while also encapsulating the package,
187+ ** preventing any other entry points besides those defined in ` "exports" ` ** .
188+ This encapsulation allows module authors to define a public interface for
189+ their package.
193190
194191If both ` "exports" ` and ` "main" ` are defined, the ` "exports" ` field takes
195- precedence over ` "main" ` .
192+ precedence over ` "main" ` . ` "exports" ` are not specific to ES modules or
193+ CommonJS; ` "main" ` will be overridden by ` "exports" ` if it exists. As such
194+ ` "main" ` cannot be used as a fallback for CommonJS but it can be used as a
195+ fallback for legacy versions of Node.js that do not support the ` "exports" `
196+ field.
197+
198+ [ Conditional Exports] [ ] can be used within ` "exports" ` to define different
199+ package entry points per environment, including whether the package is
200+ referenced via ` require ` or via ` import ` . For more information about supporting
201+ both CommonJS and ES Modules in a single package please consult
202+ [ the dual CommonJS/ES module packages section] [ ] .
203+
204+ ** Warning** : Introducing the ` "exports" ` field prevents consumers of a package
205+ from using any entry points that are not defined, including the ` package.json `
206+ (e.g. ` require('your-package/package.json') ` . ** This will likely be a breaking
207+ change.**
208+
209+ To make the introduction of ` "exports" ` non-breaking, ensure that every
210+ previously supported entry point is exported. It is best to explicitly specify
211+ entry points so that the package’s public API is well-defined. For example,
212+ a project that previous exported ` main ` , ` lib ` ,
213+ ` feature ` , and the ` package.json ` could use the following ` package.exports ` :
196214
197- Both ` "main" ` and ` "exports" ` entry points are not specific to ES modules or
198- CommonJS; ` "main" ` will be overridden by ` "exports" ` in a ` require ` so it is
199- not a CommonJS fallback.
215+ ``` json
216+ {
217+ "name" : " my-mod" ,
218+ "exports" : {
219+ "." : " ./lib/index.js" ,
220+ "./lib" : " ./lib/index.js" ,
221+ "./lib/index" : " ./lib/index.js" ,
222+ "./lib/index.js" : " ./lib/index.js" ,
223+ "./feature" : " ./feature/index.js" ,
224+ "./feature/index.js" : " ./feature/index.js" ,
225+ "./package.json" : " ./package.json"
226+ }
227+ }
228+ ```
229+
230+ Alternatively a project could choose to export entire folders:
231+
232+ ``` json
233+ {
234+ "name" : " my-mod" ,
235+ "exports" : {
236+ "." : " ./lib/index.js" ,
237+ "./lib" : " ./lib/index.js" ,
238+ "./lib/" : " ./lib/" ,
239+ "./feature" : " ./feature/index.js" ,
240+ "./feature/" : " ./feature/" ,
241+ "./package.json" : " ./package.json"
242+ }
243+ }
244+ ```
200245
201- This is important with regard to ` require ` , since ` require ` of ES module files
202- throws an error in all versions of Node.js. To create a package that works both
203- in modern Node.js via ` import ` and ` require ` and also legacy Node.js versions,
204- see [ the dual CommonJS/ES module packages section] [ ] .
246+ As a last resort, package encapsulation can be disabled entirely by creating an
247+ export for the root of the package ` "./": "./" ` . This will expose every file in
248+ the package at the cost of disabling the encapsulation and potential tooling
249+ benefits this provides. As the ES Module loader in Node.js enforces the use of
250+ [ the full specifier path] [ ] , exporting the root rather than being explicit
251+ about entry is less expressive than either of the prior examples. Not only
252+ will encapsulation be lost but module consumers will be unable to
253+ ` import feature from 'my-mod/feature' ` as they will need to provide the full
254+ path ` import feature from 'my-mod/feature/index.js ` .
205255
206256#### Main Entry Point Export
207257
@@ -1750,6 +1800,7 @@ success!
17501800[dynamic instantiate hook]: #esm_code_dynamicinstantiate_code_hook
17511801[import an ES or CommonJS module for its side effects only]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Import_a_module_for_its_side_effects_only
17521802[special scheme]: https://url.spec.whatwg.org/#special-scheme
1803+ [the full specifier path]: #esm_mandatory_file_extensions
17531804[the official standard format]: https://tc39.github.io/ecma262/#sec-modules
17541805[the dual CommonJS/ES module packages section]: #esm_dual_commonjs_es_module_packages
17551806[transpiler loader example]: #esm_transpiler_loader
0 commit comments