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