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