Skip to content

Commit bd2ce75

Browse files
guybedfordjoesepi
authored andcommitted
doc: packages docs feedback
PR-URL: nodejs#35370 Reviewed-By: Derek Lewis <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent 19449d2 commit bd2ce75

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:
@@ -815,7 +809,7 @@ changes:
815809
* Type: {string}
816810

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

820814
Files ending with `.js` will be loaded as ES modules when the nearest parent
821815
`package.json` file contains a top-level field `"type"` with a value of
@@ -839,8 +833,8 @@ node my-app.js # Runs as ES module
839833

840834
If the nearest parent `package.json` lacks a `"type"` field, or contains
841835
`"type": "commonjs"`, `.js` files are treated as [CommonJS][]. If the volume
842-
root is reached and no `package.json` is found, Node.js defers to the default
843-
treatment as [CommonJS][].
836+
root is reached and no `package.json` is found, `.js` files are treated as
837+
[CommonJS][].
844838

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

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

964957
Apart from the above, the resolution rules for the imports field are otherwise
965958
analogous to the exports field.
966959

967960
[Babel]: https://babeljs.io/
968961
[Conditional exports]: #packages_conditional_exports
969962
[CommonJS]: modules.html
970-
[entry points]: #packages_package_entry_points
971-
[`esm`]: https://github.com/standard-things/esm#readme
963+
[`ERR_PACKAGE_PATH_NOT_EXPORTED`]: errors.html#errors_err_package_path_not_exported
972964
[ES modules]: esm.html
973965
[ES module]: esm.html
966+
[`esm`]: https://github.com/standard-things/esm#readme
974967
[`"exports"`]: #packages_exports
975968
[`"main"`]: #packages_main
969+
[`"name"`]: #packages_name
970+
[`"imports"`]: #packages_imports
971+
[`"type"`]: #packages_type
972+
[entry points]: #packages_package_entry_points
976973
[`package.json`]: #packages_node_js_package_json_field_definitions
977-
[package scope]: #packages_package_scope_and_file_extensions
978974
[self-reference]: #packages_self_referencing_a_package_using_its_name
979975
[subpath exports]: #packages_subpath_exports
980976
[the full specifier path]: modules_esm.html#modules_esm_mandatory_file_extensions
981977
[the dual CommonJS/ES module packages section]: #packages_dual_commonjs_es_module_packages
982-
[`"type"`]: #packages_type

0 commit comments

Comments
 (0)