Skip to content

Commit d100516

Browse files
guybedfordMylesBorins
authored andcommitted
doc: packages docs feedback
Backport-PR-URL: #35757 PR-URL: #35370 Reviewed-By: Derek Lewis <DerekNonGeneric@inf.is> Reviewed-By: Geoffrey Booth <webmaster@geoffreybooth.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent 227ffc9 commit d100516

File tree

1 file changed

+53
-58
lines changed

1 file changed

+53
-58
lines changed

doc/api/packages.md

+53-58
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44

55
## Introduction
66

7-
A package is a folder described by a `package.json` file.
7+
A package is a folder tree described by a `package.json` file. The package
8+
consists of the folder containing the `package.json` file and all subfolders
9+
until the next folder containing another `package.json` file, or a folder
10+
named `node_modules`.
811

9-
A folder containing a `package.json` file, and all subfolders below that folder
10-
until the next folder containing another `package.json` file, are a _package
11-
scope_.
12+
This page provides guidance for package authors writing `package.json` files
13+
along with a reference for the [`package.json`][] fields defined by Node.js.
1214

1315
## Determining module system
1416

@@ -18,7 +20,7 @@ initial input, or when referenced by `import` statements within ES module code:
1820
* Files ending in `.mjs`.
1921

2022
* Files ending in `.js` when the nearest parent `package.json` file contains a
21-
top-level field [`"type"`][] with a value of `"module"`.
23+
top-level [`"type"`][] field with a value of `"module"`.
2224

2325
* Strings passed in as an argument to `--eval`, or piped to `node` via `STDIN`,
2426
with the flag `--input-type=module`.
@@ -45,29 +47,25 @@ future-proof the package in case the default type of Node.js ever changes, and
4547
it will also make things easier for build tools and loaders to determine how the
4648
files in the package should be interpreted.
4749

48-
### Package scope and file extensions
50+
### `package.json` and file extensions
4951

50-
A folder containing a `package.json` file, and all subfolders below that folder
51-
until the next folder containing another [`package.json`][], are a
52-
_package scope_. Package scopes do not carry through `node_modules` folders.
53-
54-
Within a package scope, the [`package.json`][] [`"type"`][] field defines how
52+
Within a package, the [`package.json`][] [`"type"`][] field defines how
5553
Node.js should interpret `.js` files. If a `package.json` file does not have a
5654
`"type"` field, `.js` files are treated as [CommonJS][].
5755

5856
A `package.json` `"type"` value of `"module"` tells Node.js to interpret `.js`
59-
files within that package scope as using [ES module][] syntax.
57+
files within that package as using [ES module][] syntax.
6058

61-
The package scope applies not only to initial entry points (`node my-app.js`)
59+
The `"type"` field applies not only to initial entry points (`node my-app.js`)
6260
but also to files referenced by `import` statements and `import()` expressions.
6361

6462
```js
65-
// my-app.js, in an ES module package scope because there is a package.json
63+
// my-app.js, treated as an ES module because there is a package.json
6664
// file in the same folder with "type": "module".
6765

6866
import './startup/init.js';
6967
// Loaded as ES module since ./startup contains no package.json file,
70-
// and therefore inherits the ES module package scope from one level up.
68+
// and therefore inherits the "type" value from one level up.
7169

7270
import 'commonjs-package';
7371
// Loaded as CommonJS since ./node_modules/commonjs-package/package.json
@@ -79,10 +77,10 @@ import './node_modules/commonjs-package/index.js';
7977
```
8078

8179
Files ending with `.mjs` are always loaded as [ES modules][] regardless of
82-
package scope.
80+
the nearest parent `package.json`.
8381

84-
Files ending with `.cjs` are always loaded as [CommonJS][] regardless of package
85-
scope.
82+
Files ending with `.cjs` are always loaded as [CommonJS][] regardless of the
83+
nearest parent `package.json`.
8684

8785
```js
8886
import './legacy-file.cjs';
@@ -93,17 +91,17 @@ import 'commonjs-package/src/index.mjs';
9391
```
9492

9593
The `.mjs` and `.cjs` extensions may be used to mix types within the same
96-
package scope:
94+
package:
9795

98-
* Within a `"type": "module"` package scope, Node.js can be instructed to
96+
* Within a `"type": "module"` package, Node.js can be instructed to
9997
interpret a particular file as [CommonJS][] by naming it with a `.cjs`
10098
extension (since both `.js` and `.mjs` files are treated as ES modules within
101-
a `"module"` package scope).
99+
a `"module"` package).
102100

103-
* Within a `"type": "commonjs"` package scope, Node.js can be instructed to
101+
* Within a `"type": "commonjs"` package, Node.js can be instructed to
104102
interpret a particular file as an [ES module][] by naming it with an `.mjs`
105103
extension (since both `.js` and `.cjs` files are treated as CommonJS within a
106-
`"commonjs"` package scope).
104+
`"commonjs"` package).
107105

108106
### `--input-type` flag
109107

@@ -211,10 +209,10 @@ To set the main entry point for a package, it is advisable to define both
211209
}
212210
```
213211

214-
The benefit of doing this is that when using the [`"exports"`][] field all
215-
subpaths of the package will no longer be available to importers under
216-
`require('pkg/subpath.js')`, and instead they will get a new error,
217-
`ERR_PACKAGE_PATH_NOT_EXPORTED`.
212+
When defining the [`"exports"`][] field, all subpaths of the package will be
213+
encapsulated and no longer available to importers. For example,
214+
`require('pkg/subpath.js')` would throw an [`ERR_PACKAGE_PATH_NOT_EXPORTED`][]
215+
error.
218216

219217
This encapsulation of exports provides more reliable guarantees
220218
about package interfaces for tools and when handling semver upgrades for a
@@ -295,24 +293,6 @@ treating the right hand side target pattern as a `**` glob against the list of
295293
files within the package. Because `node_modules` paths are forbidden in exports
296294
targets, this expansion is dependent on only the files of the package itself.
297295

298-
### Package exports fallbacks
299-
300-
> Stability: 1 - Experimental
301-
302-
For possible new specifier support in future, array fallbacks are
303-
supported for all invalid specifiers:
304-
305-
```json
306-
{
307-
"exports": {
308-
"./submodule": ["not:valid", "./submodule.js"]
309-
}
310-
}
311-
```
312-
313-
Since `"not:valid"` is not a valid specifier, `"./submodule.js"` is used
314-
instead as the fallback, as if it were the only target.
315-
316296
### Exports sugar
317297

318298
> Stability: 1 - Experimental
@@ -560,9 +540,10 @@ could be intended only for other environments such as browsers. Such a package
560540
would be usable by any version of Node.js, since `import` can refer to CommonJS
561541
files; but it would not provide any of the advantages of using ES module syntax.
562542

563-
A package could also switch from CommonJS to ES module syntax in a breaking
564-
change version bump. This has the disadvantage that the newest version
565-
of the package would only be usable in ES module-supporting versions of Node.js.
543+
A package could also switch from CommonJS to ES module syntax in a [breaking
544+
change](https://semver.org/) version bump. This has the disadvantage that the
545+
newest version of the package would only be usable in ES module-supporting
546+
versions of Node.js.
566547

567548
Every pattern has tradeoffs, but there are two broad approaches that satisfy the
568549
following conditions:
@@ -773,6 +754,19 @@ This section describes the fields used by the Node.js runtime. Other tools (such
773754
as [npm](https://docs.npmjs.com/creating-a-package-json-file)) may use
774755
additional fields which are ignored by Node.js and not documented here.
775756

757+
The following fields in `package.json` files are used in Node.js:
758+
759+
* [`"name"`][] - Relevant when using named imports within a package. Also used
760+
by package managers as the name of the package.
761+
* [`"type"`][] - The package type determining whether to load `.js` files as
762+
CommonJS or ES modules.
763+
* [`"exports"`][] - Package exports and conditional exports. When present,
764+
limits which submodules may be loaded from within the package.
765+
* [`"main"`][] - The default module when loading the package, if exports is not
766+
specified, and in versions of Node.js prior to the introduction of exports.
767+
* [`"imports"`][] - Package imports, for use by modules within the package
768+
itself.
769+
776770
### `"name"`
777771
<!-- YAML
778772
added:
@@ -812,7 +806,7 @@ changes:
812806
* Type: {string}
813807

814808
The `"type"` field defines the module format that Node.js will use for all
815-
`.js` files within a particular `package.json` file’s [package scope][].
809+
`.js` files that have that `package.json` file as their nearest parent.
816810

817811
Files ending with `.js` will be loaded as ES modules when the nearest parent
818812
`package.json` file contains a top-level field `"type"` with a value of
@@ -836,8 +830,8 @@ node my-app.js # Runs as ES module
836830

837831
If the nearest parent `package.json` lacks a `"type"` field, or contains
838832
`"type": "commonjs"`, `.js` files are treated as [CommonJS][]. If the volume
839-
root is reached and no `package.json` is found, Node.js defers to the default
840-
treatment as [CommonJS][].
833+
root is reached and no `package.json` is found, `.js` files are treated as
834+
[CommonJS][].
841835

842836
`import` statements of `.js` files are treated as ES modules if the nearest
843837
parent `package.json` contains `"type": "module"`.
@@ -951,26 +945,27 @@ where `import '#dep'` would now get the resolution of the external package
951945
`dep-node-native` (including its exports in turn), and instead get the local
952946
file `./dep-polyfill.js` relative to the package in other environments.
953947

954-
Unlike the exports field, import maps permit mapping to external packages
955-
because this provides an important use case for conditional loading and also can
956-
be done without the risk of cycles, unlike for exports.
948+
Unlike the `"exports"` field, import maps permit mapping to external packages,
949+
providing an important use case for conditional loading scenarios.
957950

958951
Apart from the above, the resolution rules for the imports field are otherwise
959952
analogous to the exports field.
960953

961954
[Babel]: https://babeljs.io/
962955
[Conditional exports]: #packages_conditional_exports
963956
[CommonJS]: modules.html
964-
[entry points]: #packages_package_entry_points
965-
[`esm`]: https://github.com/standard-things/esm#readme
957+
[`ERR_PACKAGE_PATH_NOT_EXPORTED`]: errors.html#errors_err_package_path_not_exported
966958
[ES modules]: esm.html
967959
[ES module]: esm.html
960+
[`esm`]: https://github.com/standard-things/esm#readme
968961
[`"exports"`]: #packages_exports
969962
[`"main"`]: #packages_main
963+
[`"name"`]: #packages_name
964+
[`"imports"`]: #packages_imports
965+
[`"type"`]: #packages_type
966+
[entry points]: #packages_package_entry_points
970967
[`package.json`]: #packages_node_js_package_json_field_definitions
971-
[package scope]: #packages_package_scope_and_file_extensions
972968
[self-reference]: #packages_self_referencing_a_package_using_its_name
973969
[subpath exports]: #packages_subpath_exports
974970
[the full specifier path]: modules_esm.html#modules_esm_mandatory_file_extensions
975971
[the dual CommonJS/ES module packages section]: #packages_dual_commonjs_es_module_packages
976-
[`"type"`]: #packages_type

0 commit comments

Comments
 (0)