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