Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMyles Borins <myles.borins@gmail.com>2020-04-26 09:47:31 +0300
committerMyles Borins <mylesborins@google.com>2020-05-05 20:48:26 +0300
commit1ffd182264dcf02e010aae3dc88406c2db9efcfb (patch)
treecdf133277f7c33c31fdeb88e9257899cd4b0fba3 /doc/api/esm.md
parent26f150022f9b4d4709c1d4ad450c6f9e9fce8d0e (diff)
doc: explicitly doc package.exports is breaking
If package authors don't explicitly include all previously supported entry points introducing package.exports will be a Semver-Major change. Add a warning about this behavior and offer two potential solutions for module authors. Refs: https://github.com/then/is-promise/issues/20 PR-URL: https://github.com/nodejs/node/pull/33074 Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Jan Krems <jan.krems@gmail.com> Reviewed-By: Geoffrey Booth <webmaster@geoffreybooth.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'doc/api/esm.md')
-rw-r--r--doc/api/esm.md81
1 files changed, 66 insertions, 15 deletions
diff --git a/doc/api/esm.md b/doc/api/esm.md
index 5047600f988..1c1317b6df7 100644
--- a/doc/api/esm.md
+++ b/doc/api/esm.md
@@ -183,25 +183,75 @@ versions of Node.js, but its capabilities are limited: it only defines the main
entry point of the package.
The `"exports"` field provides an alternative to `"main"` where the package
-main entry point can be defined while also encapsulating the package, preventing
-any other entry points besides those defined in `"exports"`. If package entry
-points are defined in both `"main"` and `"exports"`, the latter takes precedence
-in versions of Node.js that support `"exports"`. [Conditional Exports][] can
-also be used within `"exports"` to define different package entry points per
-environment, including whether the package is referenced via `require` or via
-`import`.
+main entry point can be defined while also encapsulating the package,
+**preventing any other entry points besides those defined in `"exports"`**.
+This encapsulation allows module authors to define a public interface for
+their package.
If both `"exports"` and `"main"` are defined, the `"exports"` field takes
-precedence over `"main"`.
+precedence over `"main"`. `"exports"` are not specific to ES modules or
+CommonJS; `"main"` will be overridden by `"exports"` if it exists. As such
+`"main"` cannot be used as a fallback for CommonJS but it can be used as a
+fallback for legacy versions of Node.js that do not support the `"exports"`
+field.
+
+[Conditional Exports][] can be used within `"exports"` to define different
+package entry points per environment, including whether the package is
+referenced via `require` or via `import`. For more information about supporting
+both CommonJS and ES Modules in a single package please consult
+[the dual CommonJS/ES module packages section][].
+
+**Warning**: Introducing the `"exports"` field prevents consumers of a package
+from using any entry points that are not defined, including the `package.json`
+(e.g. `require('your-package/package.json')`. **This will likely be a breaking
+change.**
+
+To make the introduction of `"exports"` non-breaking, ensure that every
+previously supported entry point is exported. It is best to explicitly specify
+entry points so that the package’s public API is well-defined. For example,
+a project that previous exported `main`, `lib`,
+`feature`, and the `package.json` could use the following `package.exports`:
-Both `"main"` and `"exports"` entry points are not specific to ES modules or
-CommonJS; `"main"` will be overridden by `"exports"` in a `require` so it is
-not a CommonJS fallback.
+```json
+{
+ "name": "my-mod",
+ "exports": {
+ ".": "./lib/index.js",
+ "./lib": "./lib/index.js",
+ "./lib/index": "./lib/index.js",
+ "./lib/index.js": "./lib/index.js",
+ "./feature": "./feature/index.js",
+ "./feature/index.js": "./feature/index.js",
+ "./package.json": "./package.json"
+ }
+}
+```
+
+Alternatively a project could choose to export entire folders:
+
+```json
+{
+ "name": "my-mod",
+ "exports": {
+ ".": "./lib/index.js",
+ "./lib": "./lib/index.js",
+ "./lib/": "./lib/",
+ "./feature": "./feature/index.js",
+ "./feature/": "./feature/",
+ "./package.json": "./package.json"
+ }
+}
+```
-This is important with regard to `require`, since `require` of ES module files
-throws an error in all versions of Node.js. To create a package that works both
-in modern Node.js via `import` and `require` and also legacy Node.js versions,
-see [the dual CommonJS/ES module packages section][].
+As a last resort, package encapsulation can be disabled entirely by creating an
+export for the root of the package `"./": "./"`. This will expose every file in
+the package at the cost of disabling the encapsulation and potential tooling
+benefits this provides. As the ES Module loader in Node.js enforces the use of
+[the full specifier path][], exporting the root rather than being explicit
+about entry is less expressive than either of the prior examples. Not only
+will encapsulation be lost but module consumers will be unable to
+`import feature from 'my-mod/feature'` as they will need to provide the full
+path `import feature from 'my-mod/feature/index.js`.
#### Main Entry Point Export
@@ -1746,6 +1796,7 @@ success!
[dynamic instantiate hook]: #esm_code_dynamicinstantiate_code_hook
[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
[special scheme]: https://url.spec.whatwg.org/#special-scheme
+[the full specifier path]: #esm_mandatory_file_extensions
[the official standard format]: https://tc39.github.io/ecma262/#sec-modules
[the dual CommonJS/ES module packages section]: #esm_dual_commonjs_es_module_packages
[transpiler loader example]: #esm_transpiler_loader