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