• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Modules: Packages
2
3<!--introduced_in=v12.20.0-->
4<!-- type=misc -->
5<!-- YAML
6changes:
7  - version:
8    - v14.13.0
9    pr-url: https://github.com/nodejs/node/pull/34718
10    description: Add support for `"exports"` patterns.
11  - version:
12    - v14.6.0
13    - v12.19.0
14    pr-url: https://github.com/nodejs/node/pull/34117
15    description: Add package `"imports"` field.
16  - version:
17    - v13.7.0
18    - v12.16.0
19    pr-url: https://github.com/nodejs/node/pull/31001
20    description: Unflag conditional exports.
21  - version:
22    - v13.6.0
23    - v12.16.0
24    pr-url: https://github.com/nodejs/node/pull/31002
25    description: Unflag self-referencing a package using its name.
26  - version: v12.7.0
27    pr-url: https://github.com/nodejs/node/pull/28568
28    description:
29      Introduce `"exports"` `package.json` field as a more powerful alternative
30      to the classic `"main"` field.
31  - version: v12.0.0
32    pr-url: https://github.com/nodejs/node/pull/26745
33    description:
34      Add support for ES modules using `.js` file extension via `package.json`
35      `"type"` field.
36-->
37
38## Introduction
39
40A package is a folder tree described by a `package.json` file. The package
41consists of the folder containing the `package.json` file and all subfolders
42until the next folder containing another `package.json` file, or a folder
43named `node_modules`.
44
45This page provides guidance for package authors writing `package.json` files
46along with a reference for the [`package.json`][] fields defined by Node.js.
47
48## Determining module system
49
50Node.js will treat the following as [ES modules][] when passed to `node` as the
51initial input, or when referenced by `import` statements within ES module code:
52
53* Files ending in `.mjs`.
54
55* Files ending in `.js` when the nearest parent `package.json` file contains a
56  top-level [`"type"`][] field with a value of `"module"`.
57
58* Strings passed in as an argument to `--eval`, or piped to `node` via `STDIN`,
59  with the flag `--input-type=module`.
60
61Node.js will treat as [CommonJS][] all other forms of input, such as `.js` files
62where the nearest parent `package.json` file contains no top-level `"type"`
63field, or string input without the flag `--input-type`. This behavior is to
64preserve backward compatibility. However, now that Node.js supports both
65CommonJS and ES modules, it is best to be explicit whenever possible. Node.js
66will treat the following as CommonJS when passed to `node` as the initial input,
67or when referenced by `import` statements within ES module code:
68
69* Files ending in `.cjs`.
70
71* Files ending in `.js` when the nearest parent `package.json` file contains a
72  top-level field [`"type"`][] with a value of `"commonjs"`.
73
74* Strings passed in as an argument to `--eval` or `--print`, or piped to `node`
75  via `STDIN`, with the flag `--input-type=commonjs`.
76
77Package authors should include the [`"type"`][] field, even in packages where
78all sources are CommonJS. Being explicit about the `type` of the package will
79future-proof the package in case the default type of Node.js ever changes, and
80it will also make things easier for build tools and loaders to determine how the
81files in the package should be interpreted.
82
83### `package.json` and file extensions
84
85Within a package, the [`package.json`][] [`"type"`][] field defines how
86Node.js should interpret `.js` files. If a `package.json` file does not have a
87`"type"` field, `.js` files are treated as [CommonJS][].
88
89A `package.json` `"type"` value of `"module"` tells Node.js to interpret `.js`
90files within that package as using [ES module][] syntax.
91
92The `"type"` field applies not only to initial entry points (`node my-app.js`)
93but also to files referenced by `import` statements and `import()` expressions.
94
95```js
96// my-app.js, treated as an ES module because there is a package.json
97// file in the same folder with "type": "module".
98
99import './startup/init.js';
100// Loaded as ES module since ./startup contains no package.json file,
101// and therefore inherits the "type" value from one level up.
102
103import 'commonjs-package';
104// Loaded as CommonJS since ./node_modules/commonjs-package/package.json
105// lacks a "type" field or contains "type": "commonjs".
106
107import './node_modules/commonjs-package/index.js';
108// Loaded as CommonJS since ./node_modules/commonjs-package/package.json
109// lacks a "type" field or contains "type": "commonjs".
110```
111
112Files ending with `.mjs` are always loaded as [ES modules][] regardless of
113the nearest parent `package.json`.
114
115Files ending with `.cjs` are always loaded as [CommonJS][] regardless of the
116nearest parent `package.json`.
117
118```js
119import './legacy-file.cjs';
120// Loaded as CommonJS since .cjs is always loaded as CommonJS.
121
122import 'commonjs-package/src/index.mjs';
123// Loaded as ES module since .mjs is always loaded as ES module.
124```
125
126The `.mjs` and `.cjs` extensions can be used to mix types within the same
127package:
128
129* Within a `"type": "module"` package, Node.js can be instructed to
130  interpret a particular file as [CommonJS][] by naming it with a `.cjs`
131  extension (since both `.js` and `.mjs` files are treated as ES modules within
132  a `"module"` package).
133
134* Within a `"type": "commonjs"` package, Node.js can be instructed to
135  interpret a particular file as an [ES module][] by naming it with an `.mjs`
136  extension (since both `.js` and `.cjs` files are treated as CommonJS within a
137  `"commonjs"` package).
138
139### `--input-type` flag
140<!-- YAML
141added: v12.0.0
142-->
143
144Strings passed in as an argument to `--eval` (or `-e`), or piped to `node` via
145`STDIN`, are treated as [ES modules][] when the `--input-type=module` flag
146is set.
147
148```bash
149node --input-type=module --eval "import { sep } from 'path'; console.log(sep);"
150
151echo "import { sep } from 'path'; console.log(sep);" | node --input-type=module
152```
153
154For completeness there is also `--input-type=commonjs`, for explicitly running
155string input as CommonJS. This is the default behavior if `--input-type` is
156unspecified.
157
158## Determining package manager
159
160> Stability: 1 - Experimental
161
162While all Node.js projects are expected to be installable by all package
163managers once published, their development teams are often required to use one
164specific package manager. To make this process easier, Node.js ships with a
165tool called [Corepack][] that aims to make all package managers transparently
166available in your environment - provided you have Node.js installed.
167
168By default Corepack won't enforce any specific package manager and will use
169the generic "Last Known Good" versions associated with each Node.js release,
170but you can improve this experience by setting the [`"packageManager"`][] field
171in your project's `package.json`.
172
173## Package entry points
174
175In a package’s `package.json` file, two fields can define entry points for a
176package: [`"main"`][] and [`"exports"`][]. The [`"main"`][] field is supported
177in all versions of Node.js, but its capabilities are limited: it only defines
178the main entry point of the package.
179
180The [`"exports"`][] field provides an alternative to [`"main"`][] where the
181package main entry point can be defined while also encapsulating the package,
182**preventing any other entry points besides those defined in [`"exports"`][]**.
183This encapsulation allows module authors to define a public interface for
184their package.
185
186If both [`"exports"`][] and [`"main"`][] are defined, the [`"exports"`][] field
187takes precedence over [`"main"`][]. [`"exports"`][] are not specific to ES
188modules or CommonJS; [`"main"`][] is overridden by [`"exports"`][] if it
189exists. As such [`"main"`][] cannot be used as a fallback for CommonJS but it
190can be used as a fallback for legacy versions of Node.js that do not support the
191[`"exports"`][] field.
192
193[Conditional exports][] can be used within [`"exports"`][] to define different
194package entry points per environment, including whether the package is
195referenced via `require` or via `import`. For more information about supporting
196both CommonJS and ES Modules in a single package please consult
197[the dual CommonJS/ES module packages section][].
198
199**Warning**: Introducing the [`"exports"`][] field prevents consumers of a
200package from using any entry points that are not defined, including the
201[`package.json`][] (e.g. `require('your-package/package.json')`. **This will
202likely be a breaking change.**
203
204To make the introduction of [`"exports"`][] non-breaking, ensure that every
205previously supported entry point is exported. It is best to explicitly specify
206entry points so that the package’s public API is well-defined. For example,
207a project that previous exported `main`, `lib`,
208`feature`, and the `package.json` could use the following `package.exports`:
209
210```json
211{
212  "name": "my-mod",
213  "exports": {
214    ".": "./lib/index.js",
215    "./lib": "./lib/index.js",
216    "./lib/index": "./lib/index.js",
217    "./lib/index.js": "./lib/index.js",
218    "./feature": "./feature/index.js",
219    "./feature/index.js": "./feature/index.js",
220    "./package.json": "./package.json"
221  }
222}
223```
224
225Alternatively a project could choose to export entire folders:
226
227```json
228{
229  "name": "my-mod",
230  "exports": {
231    ".": "./lib/index.js",
232    "./lib": "./lib/index.js",
233    "./lib/*": "./lib/*.js",
234    "./feature": "./feature/index.js",
235    "./feature/*": "./feature/*.js",
236    "./package.json": "./package.json"
237  }
238}
239```
240
241As a last resort, package encapsulation can be disabled entirely by creating an
242export for the root of the package `"./*": "./*"`. This exposes every file
243in the package at the cost of disabling the encapsulation and potential tooling
244benefits this provides. As the ES Module loader in Node.js enforces the use of
245[the full specifier path][], exporting the root rather than being explicit
246about entry is less expressive than either of the prior examples. Not only
247is encapsulation lost but module consumers are unable to
248`import feature from 'my-mod/feature'` as they need to provide the full
249path `import feature from 'my-mod/feature/index.js`.
250
251### Main entry point export
252
253To set the main entry point for a package, it is advisable to define both
254[`"exports"`][] and [`"main"`][] in the package’s [`package.json`][] file:
255
256```json
257{
258  "main": "./main.js",
259  "exports": "./main.js"
260}
261```
262
263When the [`"exports"`][] field is defined, all subpaths of the package are
264encapsulated and no longer available to importers. For example,
265`require('pkg/subpath.js')` throws an [`ERR_PACKAGE_PATH_NOT_EXPORTED`][]
266error.
267
268This encapsulation of exports provides more reliable guarantees
269about package interfaces for tools and when handling semver upgrades for a
270package. It is not a strong encapsulation since a direct require of any
271absolute subpath of the package such as
272`require('/path/to/node_modules/pkg/subpath.js')` will still load `subpath.js`.
273
274### Subpath exports
275<!-- YAML
276added: v12.7.0
277-->
278
279When using the [`"exports"`][] field, custom subpaths can be defined along
280with the main entry point by treating the main entry point as the
281`"."` subpath:
282
283```json
284{
285  "main": "./main.js",
286  "exports": {
287    ".": "./main.js",
288    "./submodule": "./src/submodule.js"
289  }
290}
291```
292
293Now only the defined subpath in [`"exports"`][] can be imported by a consumer:
294
295```js
296import submodule from 'es-module-package/submodule';
297// Loads ./node_modules/es-module-package/src/submodule.js
298```
299
300While other subpaths will error:
301
302```js
303import submodule from 'es-module-package/private-module.js';
304// Throws ERR_PACKAGE_PATH_NOT_EXPORTED
305```
306
307### Subpath imports
308<!-- YAML
309added:
310  - v14.6.0
311  - v12.19.0
312-->
313
314In addition to the [`"exports"`][] field, it is possible to define internal
315package import maps that only apply to import specifiers from within the package
316itself.
317
318Entries in the imports field must always start with `#` to ensure they are
319disambiguated from package specifiers.
320
321For example, the imports field can be used to gain the benefits of conditional
322exports for internal modules:
323
324```json
325// package.json
326{
327  "imports": {
328    "#dep": {
329      "node": "dep-node-native",
330      "default": "./dep-polyfill.js"
331    }
332  },
333  "dependencies": {
334    "dep-node-native": "^1.0.0"
335  }
336}
337```
338
339where `import '#dep'` does not get the resolution of the external package
340`dep-node-native` (including its exports in turn), and instead gets the local
341file `./dep-polyfill.js` relative to the package in other environments.
342
343Unlike the `"exports"` field, the `"imports"` field permits mapping to external
344packages.
345
346The resolution rules for the imports field are otherwise
347analogous to the exports field.
348
349### Subpath patterns
350<!-- YAML
351added:
352  - v14.13.0
353  - v12.20.0
354-->
355
356For packages with a small number of exports or imports, we recommend
357explicitly listing each exports subpath entry. But for packages that have
358large numbers of subpaths, this might cause `package.json` bloat and
359maintenance issues.
360
361For these use cases, subpath export patterns can be used instead:
362
363```json
364// ./node_modules/es-module-package/package.json
365{
366  "exports": {
367    "./features/*": "./src/features/*.js"
368  },
369  "imports": {
370    "#internal/*": "./src/internal/*.js"
371  }
372}
373```
374
375**`*` maps expose nested subpaths as it is a string replacement syntax
376only.**
377
378All instances of `*` on the right hand side will then be replaced with this
379value, including if it contains any `/` separators.
380
381```js
382import featureX from 'es-module-package/features/x';
383// Loads ./node_modules/es-module-package/src/features/x.js
384
385import featureY from 'es-module-package/features/y/y';
386// Loads ./node_modules/es-module-package/src/features/y/y.js
387
388import internalZ from '#internal/z';
389// Loads ./node_modules/es-module-package/src/internal/z.js
390```
391
392This is a direct static replacement without any special handling for file
393extensions. In the previous example, `pkg/features/x.json` would be resolved to
394`./src/features/x.json.js` in the mapping.
395
396The property of exports being statically enumerable is maintained with exports
397patterns since the individual exports for a package can be determined by
398treating the right hand side target pattern as a `**` glob against the list of
399files within the package. Because `node_modules` paths are forbidden in exports
400targets, this expansion is dependent on only the files of the package itself.
401
402To exclude private subfolders from patterns, `null` targets can be used:
403
404```json
405// ./node_modules/es-module-package/package.json
406{
407  "exports": {
408    "./features/*": "./src/features/*.js",
409    "./features/private-internal/*": null
410  }
411}
412```
413
414```js
415import featureInternal from 'es-module-package/features/private-internal/m';
416// Throws: ERR_PACKAGE_PATH_NOT_EXPORTED
417
418import featureX from 'es-module-package/features/x';
419// Loads ./node_modules/es-module-package/src/features/x.js
420```
421
422### Exports sugar
423<!-- YAML
424added: v12.11.0
425-->
426
427If the `"."` export is the only export, the [`"exports"`][] field provides sugar
428for this case being the direct [`"exports"`][] field value.
429
430If the `"."` export has a fallback array or string value, then the
431[`"exports"`][] field can be set to this value directly.
432
433```json
434{
435  "exports": {
436    ".": "./main.js"
437  }
438}
439```
440
441can be written:
442
443```json
444{
445  "exports": "./main.js"
446}
447```
448
449### Conditional exports
450<!-- YAML
451added:
452  - v13.2.0
453  - v12.16.0
454changes:
455  - version:
456    - v13.7.0
457    - v12.16.0
458    pr-url: https://github.com/nodejs/node/pull/31001
459    description: Unflag conditional exports.
460-->
461
462Conditional exports provide a way to map to different paths depending on
463certain conditions. They are supported for both CommonJS and ES module imports.
464
465For example, a package that wants to provide different ES module exports for
466`require()` and `import` can be written:
467
468```json
469// package.json
470{
471  "main": "./main-require.cjs",
472  "exports": {
473    "import": "./main-module.js",
474    "require": "./main-require.cjs"
475  },
476  "type": "module"
477}
478```
479
480Node.js implements the following conditions:
481
482* `"import"` - matches when the package is loaded via `import` or
483   `import()`, or via any top-level import or resolve operation by the
484   ECMAScript module loader. Applies regardless of the module format of the
485   target file. _Always mutually exclusive with `"require"`._
486* `"require"` - matches when the package is loaded via `require()`. The
487   referenced file should be loadable with `require()` although the condition
488   matches regardless of the module format of the target file. Expected
489   formats include CommonJS, JSON, and native addons but not ES modules as
490   `require()` doesn't support them. _Always mutually exclusive with
491   `"import"`._
492* `"node"` - matches for any Node.js environment. Can be a CommonJS or ES
493   module file. _This condition should always come after `"import"` or
494   `"require"`._
495* `"node-addons"` - similar to `"node"` and matches for any Node.js environment.
496   This condition can be used to provide an entry point which uses native C++
497   addons as opposed to an entry point which is more universal and doesn't rely
498   on native addons. This condition can be disabled via the
499   [`--no-addons` flag][].
500* `"default"` - the generic fallback that always matches. Can be a CommonJS
501   or ES module file. _This condition should always come last._
502
503Within the [`"exports"`][] object, key order is significant. During condition
504matching, earlier entries have higher priority and take precedence over later
505entries. _The general rule is that conditions should be from most specific to
506least specific in object order_.
507
508Using the `"import"` and `"require"` conditions can lead to some hazards,
509which are further explained in [the dual CommonJS/ES module packages section][].
510
511Conditional exports can also be extended to exports subpaths, for example:
512
513```json
514{
515  "main": "./main.js",
516  "exports": {
517    ".": "./main.js",
518    "./feature": {
519      "node": "./feature-node.js",
520      "default": "./feature.js"
521    }
522  }
523}
524```
525
526Defines a package where `require('pkg/feature')` and `import 'pkg/feature'`
527could provide different implementations between Node.js and other JS
528environments.
529
530When using environment branches, always include a `"default"` condition where
531possible. Providing a `"default"` condition ensures that any unknown JS
532environments are able to use this universal implementation, which helps avoid
533these JS environments from having to pretend to be existing environments in
534order to support packages with conditional exports. For this reason, using
535`"node"` and `"default"` condition branches is usually preferable to using
536`"node"` and `"browser"` condition branches.
537
538### Nested conditions
539
540In addition to direct mappings, Node.js also supports nested condition objects.
541
542For example, to define a package that only has dual mode entry points for
543use in Node.js but not the browser:
544
545```json
546{
547  "main": "./main.js",
548  "exports": {
549    "node": {
550      "import": "./feature-node.mjs",
551      "require": "./feature-node.cjs"
552    },
553    "default": "./feature.mjs",
554  }
555}
556```
557
558Conditions continue to be matched in order as with flat conditions. If
559a nested conditional does not have any mapping it will continue checking
560the remaining conditions of the parent condition. In this way nested
561conditions behave analogously to nested JavaScript `if` statements.
562
563### Resolving user conditions
564<!-- YAML
565added:
566  - v14.9.0
567  - v12.19.0
568-->
569
570When running Node.js, custom user conditions can be added with the
571`--conditions` flag:
572
573```bash
574node --conditions=development main.js
575```
576
577which would then resolve the `"development"` condition in package imports and
578exports, while resolving the existing `"node"`, `"node-addons"`, `"default"`,
579`"import"`, and `"require"` conditions as appropriate.
580
581Any number of custom conditions can be set with repeat flags.
582
583### Conditions Definitions
584
585The `"import"`, `"require"`, `"node"`, `"node-addons"` and `"default"`
586conditions are defined and implemented in Node.js core,
587[as specified above](#packages_conditional_exports).
588
589The `"node-addons"` condition can be used to provide an entry point which
590uses native C++ addons. However, this condition can be disabled via the
591[`--no-addons` flag][]. When using `"node-addons"`, it's recommended to treat
592`"default"` as an enhancement that provides a more universal entry point, e.g.
593using WebAssembly instead of a native addon.
594
595Other condition strings are unknown to Node.js and thus ignored by default.
596Runtimes or tools other than Node.js can use them at their discretion.
597
598These user conditions can be enabled in Node.js via the [`--conditions`
599flag](#packages_resolving_user_conditions).
600
601The following condition definitions are currently endorsed by Node.js:
602
603* `"browser"` - any environment which implements a standard subset of global
604   browser APIs available from JavaScript in web browsers, including the DOM
605   APIs.
606* `"development"` - can be used to define a development-only environment
607   entry point. _Must always be mutually exclusive with `"production"`._
608* `"production"` - can be used to define a production environment entry
609   point. _Must always be mutually exclusive with `"development"`._
610
611The above user conditions can be enabled in Node.js via the [`--conditions`
612flag](#packages_resolving_user_conditions).
613
614Platform specific conditions such as `"deno"`, `"electron"`, or `"react-native"`
615may be used, but while there remain no implementation or integration intent
616from these platforms, the above are not explicitly endorsed by Node.js.
617
618New conditions definitions may be added to this list by creating a pull request
619to the [Node.js documentation for this section][]. The requirements for listing
620a new condition definition here are that:
621
622* The definition should be clear and unambiguous for all implementers.
623* The use case for why the condition is needed should be clearly justified.
624* There should exist sufficient existing implementation usage.
625* The condition name should not conflict with another condition definition or
626  condition in wide usage.
627* The listing of the condition definition should provide a coordination
628  benefit to the ecosystem that wouldn't otherwise be possible. For example,
629  this would not necessarily be the case for company-specific or
630  application-specific conditions.
631
632The above definitions may be moved to a dedicated conditions registry in due
633course.
634
635### Self-referencing a package using its name
636<!-- YAML
637added:
638  - v13.1.0
639  - v12.16.0
640changes:
641  - version:
642    - v13.6.0
643    - v12.16.0
644    pr-url: https://github.com/nodejs/node/pull/31002
645    description: Unflag self-referencing a package using its name.
646-->
647
648Within a package, the values defined in the package’s
649`package.json` [`"exports"`][] field can be referenced via the package’s name.
650For example, assuming the `package.json` is:
651
652```json
653// package.json
654{
655  "name": "a-package",
656  "exports": {
657    ".": "./main.mjs",
658    "./foo": "./foo.js"
659  }
660}
661```
662
663Then any module _in that package_ can reference an export in the package itself:
664
665```js
666// ./a-module.mjs
667import { something } from 'a-package'; // Imports "something" from ./main.mjs.
668```
669
670Self-referencing is available only if `package.json` has [`"exports"`][], and
671will allow importing only what that [`"exports"`][] (in the `package.json`)
672allows. So the code below, given the previous package, will generate a runtime
673error:
674
675```js
676// ./another-module.mjs
677
678// Imports "another" from ./m.mjs. Fails because
679// the "package.json" "exports" field
680// does not provide an export named "./m.mjs".
681import { another } from 'a-package/m.mjs';
682```
683
684Self-referencing is also available when using `require`, both in an ES module,
685and in a CommonJS one. For example, this code will also work:
686
687```cjs
688// ./a-module.js
689const { something } = require('a-package/foo'); // Loads from ./foo.js.
690```
691
692Finally, self-referencing also works with scoped packages. For example, this
693code will also work:
694
695```json
696// package.json
697{
698  "name": "@my/package",
699  "exports": "./index.js"
700}
701```
702
703```cjs
704// ./index.js
705module.exports = 42;
706```
707
708```cjs
709// ./other.js
710console.log(require('@my/package'));
711```
712
713```console
714$ node other.js
71542
716```
717
718## Dual CommonJS/ES module packages
719
720Prior to the introduction of support for ES modules in Node.js, it was a common
721pattern for package authors to include both CommonJS and ES module JavaScript
722sources in their package, with `package.json` [`"main"`][] specifying the
723CommonJS entry point and `package.json` `"module"` specifying the ES module
724entry point.
725This enabled Node.js to run the CommonJS entry point while build tools such as
726bundlers used the ES module entry point, since Node.js ignored (and still
727ignores) the top-level `"module"` field.
728
729Node.js can now run ES module entry points, and a package can contain both
730CommonJS and ES module entry points (either via separate specifiers such as
731`'pkg'` and `'pkg/es-module'`, or both at the same specifier via [Conditional
732exports][]). Unlike in the scenario where `"module"` is only used by bundlers,
733or ES module files are transpiled into CommonJS on the fly before evaluation by
734Node.js, the files referenced by the ES module entry point are evaluated as ES
735modules.
736
737### Dual package hazard
738
739When an application is using a package that provides both CommonJS and ES module
740sources, there is a risk of certain bugs if both versions of the package get
741loaded. This potential comes from the fact that the `pkgInstance` created by
742`const pkgInstance = require('pkg')` is not the same as the `pkgInstance`
743created by `import pkgInstance from 'pkg'` (or an alternative main path like
744`'pkg/module'`). This is the “dual package hazard,” where two versions of the
745same package can be loaded within the same runtime environment. While it is
746unlikely that an application or package would intentionally load both versions
747directly, it is common for an application to load one version while a dependency
748of the application loads the other version. This hazard can happen because
749Node.js supports intermixing CommonJS and ES modules, and can lead to unexpected
750behavior.
751
752If the package main export is a constructor, an `instanceof` comparison of
753instances created by the two versions returns `false`, and if the export is an
754object, properties added to one (like `pkgInstance.foo = 3`) are not present on
755the other. This differs from how `import` and `require` statements work in
756all-CommonJS or all-ES module environments, respectively, and therefore is
757surprising to users. It also differs from the behavior users are familiar with
758when using transpilation via tools like [Babel][] or [`esm`][].
759
760### Writing dual packages while avoiding or minimizing hazards
761
762First, the hazard described in the previous section occurs when a package
763contains both CommonJS and ES module sources and both sources are provided for
764use in Node.js, either via separate main entry points or exported paths. A
765package might instead be written where any version of Node.js receives only
766CommonJS sources, and any separate ES module sources the package might contain
767are intended only for other environments such as browsers. Such a package
768would be usable by any version of Node.js, since `import` can refer to CommonJS
769files; but it would not provide any of the advantages of using ES module syntax.
770
771A package might also switch from CommonJS to ES module syntax in a [breaking
772change](https://semver.org/) version bump. This has the disadvantage that the
773newest version of the package would only be usable in ES module-supporting
774versions of Node.js.
775
776Every pattern has tradeoffs, but there are two broad approaches that satisfy the
777following conditions:
778
7791. The package is usable via both `require` and `import`.
7801. The package is usable in both current Node.js and older versions of Node.js
781   that lack support for ES modules.
7821. The package main entry point, e.g. `'pkg'` can be used by both `require` to
783   resolve to a CommonJS file and by `import` to resolve to an ES module file.
784   (And likewise for exported paths, e.g. `'pkg/feature'`.)
7851. The package provides named exports, e.g. `import { name } from 'pkg'` rather
786   than `import pkg from 'pkg'; pkg.name`.
7871. The package is potentially usable in other ES module environments such as
788   browsers.
7891. The hazards described in the previous section are avoided or minimized.
790
791#### Approach #1: Use an ES module wrapper
792
793Write the package in CommonJS or transpile ES module sources into CommonJS, and
794create an ES module wrapper file that defines the named exports. Using
795[Conditional exports][], the ES module wrapper is used for `import` and the
796CommonJS entry point for `require`.
797
798```json
799// ./node_modules/pkg/package.json
800{
801  "type": "module",
802  "main": "./index.cjs",
803  "exports": {
804    "import": "./wrapper.mjs",
805    "require": "./index.cjs"
806  }
807}
808```
809
810The preceding example uses explicit extensions `.mjs` and `.cjs`.
811If your files use the `.js` extension, `"type": "module"` will cause such files
812to be treated as ES modules, just as `"type": "commonjs"` would cause them
813to be treated as CommonJS.
814See [Enabling](esm.md#esm_enabling).
815
816```cjs
817// ./node_modules/pkg/index.cjs
818exports.name = 'value';
819```
820
821```js
822// ./node_modules/pkg/wrapper.mjs
823import cjsModule from './index.cjs';
824export const name = cjsModule.name;
825```
826
827In this example, the `name` from `import { name } from 'pkg'` is the same
828singleton as the `name` from `const { name } = require('pkg')`. Therefore `===`
829returns `true` when comparing the two `name`s and the divergent specifier hazard
830is avoided.
831
832If the module is not simply a list of named exports, but rather contains a
833unique function or object export like `module.exports = function () { ... }`,
834or if support in the wrapper for the `import pkg from 'pkg'` pattern is desired,
835then the wrapper would instead be written to export the default optionally
836along with any named exports as well:
837
838```js
839import cjsModule from './index.cjs';
840export const name = cjsModule.name;
841export default cjsModule;
842```
843
844This approach is appropriate for any of the following use cases:
845* The package is currently written in CommonJS and the author would prefer not
846  to refactor it into ES module syntax, but wishes to provide named exports for
847  ES module consumers.
848* The package has other packages that depend on it, and the end user might
849  install both this package and those other packages. For example a `utilities`
850  package is used directly in an application, and a `utilities-plus` package
851  adds a few more functions to `utilities`. Because the wrapper exports
852  underlying CommonJS files, it doesn’t matter if `utilities-plus` is written in
853  CommonJS or ES module syntax; it will work either way.
854* The package stores internal state, and the package author would prefer not to
855  refactor the package to isolate its state management. See the next section.
856
857A variant of this approach not requiring conditional exports for consumers could
858be to add an export, e.g. `"./module"`, to point to an all-ES module-syntax
859version of the package. This could be used via `import 'pkg/module'` by users
860who are certain that the CommonJS version will not be loaded anywhere in the
861application, such as by dependencies; or if the CommonJS version can be loaded
862but doesn’t affect the ES module version (for example, because the package is
863stateless):
864
865```json
866// ./node_modules/pkg/package.json
867{
868  "type": "module",
869  "main": "./index.cjs",
870  "exports": {
871    ".": "./index.cjs",
872    "./module": "./wrapper.mjs"
873  }
874}
875```
876
877#### Approach #2: Isolate state
878
879A [`package.json`][] file can define the separate CommonJS and ES module entry
880points directly:
881
882```json
883// ./node_modules/pkg/package.json
884{
885  "type": "module",
886  "main": "./index.cjs",
887  "exports": {
888    "import": "./index.mjs",
889    "require": "./index.cjs"
890  }
891}
892```
893
894This can be done if both the CommonJS and ES module versions of the package are
895equivalent, for example because one is the transpiled output of the other; and
896the package’s management of state is carefully isolated (or the package is
897stateless).
898
899The reason that state is an issue is because both the CommonJS and ES module
900versions of the package might get used within an application; for example, the
901user’s application code could `import` the ES module version while a dependency
902`require`s the CommonJS version. If that were to occur, two copies of the
903package would be loaded in memory and therefore two separate states would be
904present. This would likely cause hard-to-troubleshoot bugs.
905
906Aside from writing a stateless package (if JavaScript’s `Math` were a package,
907for example, it would be stateless as all of its methods are static), there are
908some ways to isolate state so that it’s shared between the potentially loaded
909CommonJS and ES module instances of the package:
910
9111. If possible, contain all state within an instantiated object. JavaScript’s
912   `Date`, for example, needs to be instantiated to contain state; if it were a
913   package, it would be used like this:
914
915    ```js
916    import Date from 'date';
917    const someDate = new Date();
918    // someDate contains state; Date does not
919    ```
920
921   The `new` keyword isn’t required; a package’s function can return a new
922   object, or modify a passed-in object, to keep the state external to the
923   package.
924
9251. Isolate the state in one or more CommonJS files that are shared between the
926   CommonJS and ES module versions of the package. For example, if the CommonJS
927   and ES module entry points are `index.cjs` and `index.mjs`, respectively:
928
929    ```cjs
930    // ./node_modules/pkg/index.cjs
931    const state = require('./state.cjs');
932    module.exports.state = state;
933    ```
934
935    ```js
936    // ./node_modules/pkg/index.mjs
937    import state from './state.cjs';
938    export {
939      state
940    };
941    ```
942
943   Even if `pkg` is used via both `require` and `import` in an application (for
944   example, via `import` in application code and via `require` by a dependency)
945   each reference of `pkg` will contain the same state; and modifying that
946   state from either module system will apply to both.
947
948Any plugins that attach to the package’s singleton would need to separately
949attach to both the CommonJS and ES module singletons.
950
951This approach is appropriate for any of the following use cases:
952* The package is currently written in ES module syntax and the package author
953  wants that version to be used wherever such syntax is supported.
954* The package is stateless or its state can be isolated without too much
955  difficulty.
956* The package is unlikely to have other public packages that depend on it, or if
957  it does, the package is stateless or has state that need not be shared between
958  dependencies or with the overall application.
959
960Even with isolated state, there is still the cost of possible extra code
961execution between the CommonJS and ES module versions of a package.
962
963As with the previous approach, a variant of this approach not requiring
964conditional exports for consumers could be to add an export, e.g.
965`"./module"`, to point to an all-ES module-syntax version of the package:
966
967```json
968// ./node_modules/pkg/package.json
969{
970  "type": "module",
971  "main": "./index.cjs",
972  "exports": {
973    ".": "./index.cjs",
974    "./module": "./index.mjs"
975  }
976}
977```
978
979## Node.js `package.json` field definitions
980
981This section describes the fields used by the Node.js runtime. Other tools (such
982as [npm](https://docs.npmjs.com/creating-a-package-json-file)) use
983additional fields which are ignored by Node.js and not documented here.
984
985The following fields in `package.json` files are used in Node.js:
986
987* [`"name"`][] - Relevant when using named imports within a package. Also used
988  by package managers as the name of the package.
989* [`"main"`][] - The default module when loading the package, if exports is not
990  specified, and in versions of Node.js prior to the introduction of exports.
991* [`"packageManager"`][] - The package manager recommended when contributing to
992  the package. Leveraged by the [Corepack][] shims.
993* [`"type"`][] - The package type determining whether to load `.js` files as
994  CommonJS or ES modules.
995* [`"exports"`][] - Package exports and conditional exports. When present,
996  limits which submodules can be loaded from within the package.
997* [`"imports"`][] - Package imports, for use by modules within the package
998  itself.
999
1000### `"name"`
1001<!-- YAML
1002added:
1003  - v13.1.0
1004  - v12.16.0
1005changes:
1006  - version:
1007    - v13.6.0
1008    - v12.16.0
1009    pr-url: https://github.com/nodejs/node/pull/31002
1010    description: Remove the `--experimental-resolve-self` option.
1011-->
1012
1013* Type: {string}
1014
1015```json
1016{
1017  "name": "package-name"
1018}
1019```
1020
1021The `"name"` field defines your package’s name. Publishing to the
1022_npm_ registry requires a name that satisfies
1023[certain requirements](https://docs.npmjs.com/files/package.json#name).
1024
1025The `"name"` field can be used in addition to the [`"exports"`][] field to
1026[self-reference][] a package using its name.
1027
1028### `"main"`
1029<!-- YAML
1030added: v0.4.0
1031-->
1032
1033* Type: {string}
1034
1035```json
1036{
1037  "main": "./main.js"
1038}
1039```
1040
1041The `"main"` field defines the script that is used when the [package directory
1042is loaded via `require()`](modules.md#modules_folders_as_modules). Its value
1043is a path.
1044
1045```cjs
1046require('./path/to/directory'); // This resolves to ./path/to/directory/main.js.
1047```
1048
1049When a package has an [`"exports"`][] field, this will take precedence over the
1050`"main"` field when importing the package by name.
1051
1052### `"packageManager"`
1053<!-- YAML
1054added: v14.19.0
1055-->
1056
1057> Stability: 1 - Experimental
1058
1059* Type: {string}
1060
1061```json
1062{
1063  "packageManager": "<package manager name>@<version>"
1064}
1065```
1066
1067The `"packageManager"` field defines which package manager is expected to be
1068used when working on the current project. It can set to any of the
1069[supported package managers][], and will ensure that your teams use the exact
1070same package manager versions without having to install anything else than
1071Node.js.
1072
1073This field is currently experimental and needs to be opted-in; check the
1074[Corepack][] page for details about the procedure.
1075
1076### `"type"`
1077<!-- YAML
1078added: v12.0.0
1079changes:
1080  - version:
1081    - v13.2.0
1082    - v12.17.0
1083    pr-url: https://github.com/nodejs/node/pull/29866
1084    description: Unflag `--experimental-modules`.
1085-->
1086
1087* Type: {string}
1088
1089The `"type"` field defines the module format that Node.js uses for all
1090`.js` files that have that `package.json` file as their nearest parent.
1091
1092Files ending with `.js` are loaded as ES modules when the nearest parent
1093`package.json` file contains a top-level field `"type"` with a value of
1094`"module"`.
1095
1096The nearest parent `package.json` is defined as the first `package.json` found
1097when searching in the current folder, that folder’s parent, and so on up
1098until a node_modules folder or the volume root is reached.
1099
1100```json
1101// package.json
1102{
1103  "type": "module"
1104}
1105```
1106
1107```bash
1108# In same folder as preceding package.json
1109node my-app.js # Runs as ES module
1110```
1111
1112If the nearest parent `package.json` lacks a `"type"` field, or contains
1113`"type": "commonjs"`, `.js` files are treated as [CommonJS][]. If the volume
1114root is reached and no `package.json` is found, `.js` files are treated as
1115[CommonJS][].
1116
1117`import` statements of `.js` files are treated as ES modules if the nearest
1118parent `package.json` contains `"type": "module"`.
1119
1120```js
1121// my-app.js, part of the same example as above
1122import './startup.js'; // Loaded as ES module because of package.json
1123```
1124
1125Regardless of the value of the `"type"` field, `.mjs` files are always treated
1126as ES modules and `.cjs` files are always treated as CommonJS.
1127
1128### `"exports"`
1129<!-- YAML
1130added: v12.7.0
1131changes:
1132  - version:
1133    - v14.13.0
1134    - v12.20.0
1135    pr-url: https://github.com/nodejs/node/pull/34718
1136    description: Add support for `"exports"` patterns.
1137  - version:
1138    - v13.7.0
1139    - v12.16.0
1140    pr-url: https://github.com/nodejs/node/pull/31008
1141    description: Implement logical conditional exports ordering.
1142  - version:
1143    - v13.7.0
1144    - v12.16.0
1145    pr-url: https://github.com/nodejs/node/pull/31001
1146    description: Remove the `--experimental-conditional-exports` option.
1147  - version:
1148    - v13.2.0
1149    - v12.16.0
1150    pr-url: https://github.com/nodejs/node/pull/29978
1151    description: Implement conditional exports.
1152-->
1153
1154* Type: {Object} | {string} | {string[]}
1155
1156```json
1157{
1158  "exports": "./index.js"
1159}
1160```
1161
1162The `"exports"` field allows defining the [entry points][] of a package when
1163imported by name loaded either via a `node_modules` lookup or a
1164[self-reference][] to its own name. It is supported in Node.js 12+ as an
1165alternative to the [`"main"`][] that can support defining [subpath exports][]
1166and [conditional exports][] while encapsulating internal unexported modules.
1167
1168[Conditional Exports][] can also be used within `"exports"` to define different
1169package entry points per environment, including whether the package is
1170referenced via `require` or via `import`.
1171
1172All paths defined in the `"exports"` must be relative file URLs starting with
1173`./`.
1174
1175### `"imports"`
1176<!-- YAML
1177added:
1178 - v14.6.0
1179 - v12.19.0
1180-->
1181
1182* Type: {Object}
1183
1184```json
1185// package.json
1186{
1187  "imports": {
1188    "#dep": {
1189      "node": "dep-node-native",
1190      "default": "./dep-polyfill.js"
1191    }
1192  },
1193  "dependencies": {
1194    "dep-node-native": "^1.0.0"
1195  }
1196}
1197```
1198
1199Entries in the imports field must be strings starting with `#`.
1200
1201Import maps permit mapping to external packages.
1202
1203This field defines [subpath imports][] for the current package.
1204
1205[Babel]: https://babeljs.io/
1206[CommonJS]: modules.md
1207[Conditional exports]: #packages_conditional_exports
1208[Corepack]: corepack.md
1209[ES module]: esm.md
1210[ES modules]: esm.md
1211[Node.js documentation for this section]: https://github.com/nodejs/node/blob/HEAD/doc/api/packages.md#conditions-definitions
1212[`"exports"`]: #packages_exports
1213[`"imports"`]: #packages_imports
1214[`"main"`]: #packages_main
1215[`"name"`]: #packages_name
1216[`"packageManager"`]: #packages_packagemanager
1217[`"type"`]: #packages_type
1218[`--no-addons` flag]: cli.md#cli_no_addons
1219[`ERR_PACKAGE_PATH_NOT_EXPORTED`]: errors.md#errors_err_package_path_not_exported
1220[`esm`]: https://github.com/standard-things/esm#readme
1221[`package.json`]: #packages_node_js_package_json_field_definitions
1222[entry points]: #packages_package_entry_points
1223[self-reference]: #packages_self_referencing_a_package_using_its_name
1224[subpath exports]: #packages_subpath_exports
1225[subpath imports]: #packages_subpath_imports
1226[supported package managers]: corepack.md#corepack_supported_package_managers
1227[the dual CommonJS/ES module packages section]: #packages_dual_commonjs_es_module_packages
1228[the full specifier path]: esm.md#esm_mandatory_file_extensions
1229