Modules: Packages#

History
VersionChanges
v14.13.0, v12.20.0

Add support for"exports" patterns.

v14.6.0, v12.19.0

Add package"imports" field.

v13.7.0, v12.17.0

Unflag conditional exports.

v13.7.0, v12.16.0

Remove the--experimental-conditional-exports option. In 12.16.0, conditional exports are still behind--experimental-modules.

v13.6.0, v12.16.0

Unflag self-referencing a package using its name.

v12.7.0

Introduce"exports"package.json field as a more powerful alternative to the classic"main" field.

v12.0.0

Add support for ES modules using.js file extension viapackage.json"type" field.

Introduction#

A package is a folder tree described by apackage.json file. The packageconsists of the folder containing thepackage.json file and all subfoldersuntil the next folder containing anotherpackage.json file, or a foldernamednode_modules.

This page provides guidance for package authors writingpackage.json filesalong with a reference for thepackage.json fields defined by Node.js.

Determining module system#

Introduction#

Node.js will treat the following asES modules when passed tonode as theinitial input, or when referenced byimport statements orimport()expressions:

  • Files with an.mjs extension.

  • Files with a.js extension when the nearest parentpackage.json filecontains a top-level"type" field with a value of"module".

  • Strings passed in as an argument to--eval, or piped tonode viaSTDIN,with the flag--input-type=module.

  • Code containing syntax only successfully parsed asES modules, such asimport orexport statements orimport.meta, with no explicit marker ofhow it should be interpreted. Explicit markers are.mjs or.cjsextensions,package.json"type" fields with either"module" or"commonjs" values, or the--input-type flag. Dynamicimport()expressions are supported in either CommonJS or ES modules and would not forcea file to be treated as an ES module. SeeSyntax detection.

Node.js will treat the following asCommonJS when passed tonode as theinitial input, or when referenced byimport statements orimport()expressions:

  • Files with a.cjs extension.

  • Files with a.js extension when the nearest parentpackage.json filecontains a top-level field"type" with a value of"commonjs".

  • Strings passed in as an argument to--eval or--print, or piped tonodeviaSTDIN, with the flag--input-type=commonjs.

  • Files with a.js extension with no parentpackage.json file or where thenearest parentpackage.json file lacks atype field, and where the codecan evaluate successfully as CommonJS. In other words, Node.js tries to runsuch "ambiguous" files as CommonJS first, and will retry evaluating them as ESmodules if the evaluation as CommonJS fails because the parser found ES modulesyntax.

Writing ES module syntax in "ambiguous" files incurs a performance cost, andtherefore it is encouraged that authors be explicit wherever possible. Inparticular, package authors should always include the"type" field intheirpackage.json files, even in packages where all sources are CommonJS.Being explicit about thetype of the package will future-proof the package incase the default type of Node.js ever changes, and it will also make thingseasier for build tools and loaders to determine how the files in the packageshould be interpreted.

Syntax detection#

History
VersionChanges
v22.7.0

Syntax detection is enabled by default.

v21.1.0, v20.10.0

Added in: v21.1.0, v20.10.0

Stability: 1.2 - Release candidate

Node.js will inspect the source code of ambiguous input to determine whether itcontains ES module syntax; if such syntax is detected, the input will be treatedas an ES module.

Ambiguous input is defined as:

  • Files with a.js extension or no extension; and either no controllingpackage.json file or one that lacks atype field.
  • String input (--eval orSTDIN) when--input-typeis not specified.

ES module syntax is defined as syntax that would throw when evaluated asCommonJS. This includes the following:

  • import statements (butnotimport() expressions, which are valid inCommonJS).
  • export statements.
  • import.meta references.
  • await at the top level of a module.
  • Lexical redeclarations of the CommonJS wrapper variables (require,module,exports,__dirname,__filename).

Modules loaders#

Node.js has two systems for resolving a specifier and loading modules.

There is the CommonJS module loader:

  • It is fully synchronous.
  • It is responsible for handlingrequire() calls.
  • It is monkey patchable.
  • It supportsfolders as modules.
  • When resolving a specifier, if no exact match is found, it will try to addextensions (.js,.json, and finally.node) and then attempt to resolvefolders as modules.
  • It treats.json as JSON text files.
  • .node files are interpreted as compiled addon modules loaded withprocess.dlopen().
  • It treats all files that lack.json or.node extensions as JavaScripttext files.
  • It can only be used toload ECMAScript modules from CommonJS modules ifthe module graph is synchronous (that contains no top-levelawait).When used to load a JavaScript text file that is not an ECMAScript module,the file will be loaded as a CommonJS module.

There is the ECMAScript module loader:

  • It is asynchronous, unless it's being used to load modules forrequire().
  • It is responsible for handlingimport statements andimport() expressions.
  • It is not monkey patchable, can be customized usingloader hooks.
  • It does not support folders as modules, directory indexes (e.g.'./startup/index.js') must be fully specified.
  • It does no extension searching. A file extension must be providedwhen the specifier is a relative or absolute file URL.
  • It can load JSON modules, but an import type attribute is required.
  • It accepts only.js,.mjs, and.cjs extensions for JavaScript textfiles.
  • It can be used to load JavaScript CommonJS modules. Such modulesare passed through thecjs-module-lexer to try to identify named exports,which are available if they can be determined through static analysis.Imported CommonJS modules have their URLs converted to absolutepaths and are then loaded via the CommonJS module loader.

package.json and file extensions#

Within a package, thepackage.json"type" field defines howNode.js should interpret.js files. If apackage.json file does not have a"type" field,.js files are treated asCommonJS.

Apackage.json"type" value of"module" tells Node.js to interpret.jsfiles within that package as usingES module syntax.

The"type" field applies not only to initial entry points (node my-app.js)but also to files referenced byimport statements andimport() expressions.

// my-app.js, treated as an ES module because there is a package.json// file in the same folder with "type": "module".import'./startup/init.js';// Loaded as ES module since ./startup contains no package.json file,// and therefore inherits the "type" value from one level up.import'commonjs-package';// Loaded as CommonJS since ./node_modules/commonjs-package/package.json// lacks a "type" field or contains "type": "commonjs".import'./node_modules/commonjs-package/index.js';// Loaded as CommonJS since ./node_modules/commonjs-package/package.json// lacks a "type" field or contains "type": "commonjs".

Files ending with.mjs are always loaded asES modules regardless ofthe nearest parentpackage.json.

Files ending with.cjs are always loaded asCommonJS regardless of thenearest parentpackage.json.

import'./legacy-file.cjs';// Loaded as CommonJS since .cjs is always loaded as CommonJS.import'commonjs-package/src/index.mjs';// Loaded as ES module since .mjs is always loaded as ES module.

The.mjs and.cjs extensions can be used to mix types within the samepackage:

  • Within a"type": "module" package, Node.js can be instructed tointerpret a particular file asCommonJS by naming it with a.cjsextension (since both.js and.mjs files are treated as ES modules withina"module" package).

  • Within a"type": "commonjs" package, Node.js can be instructed tointerpret a particular file as anES module by naming it with an.mjsextension (since both.js and.cjs files are treated as CommonJS within a"commonjs" package).

--input-type flag#

Added in: v12.0.0

Strings passed in as an argument to--eval (or-e), or piped tonode viaSTDIN, are treated asES modules when the--input-type=module flagis set.

node --input-type=module --eval"import { sep } from 'node:path'; console.log(sep);"echo"import { sep } from 'node:path'; console.log(sep);" | node --input-type=module

For completeness there is also--input-type=commonjs, for explicitly runningstring input as CommonJS. This is the default behavior if--input-type isunspecified.

Package entry points#

In a package'spackage.json file, two fields can define entry points for apackage:"main" and"exports". Both fields apply to both ES moduleand CommonJS module entry points.

The"main" field is supported in all versions of Node.js, but itscapabilities are limited: it only defines the main entry point of the package.

The"exports" provides a modern alternative to"main" allowingmultiple entry points to be defined, conditional entry resolution supportbetween environments, andpreventing any other entry points besides thosedefined in"exports". This encapsulation allows module authors toclearly define the public interface for their package.

For new packages targeting the currently supported versions of Node.js, the"exports" field is recommended. For packages supporting Node.js 10 andbelow, the"main" field is required. If both"exports" and"main" are defined, the"exports" field takes precedence over"main" in supported versions of Node.js.

Conditional exports can be used within"exports" to define differentpackage entry points per environment, including whether the package isreferenced viarequire or viaimport. For more information about supportingboth CommonJS and ES modules in a single package please consultthe dual CommonJS/ES module packages section.

Existing packages introducing the"exports" field will prevent consumersof the package from using any entry points that are not defined, including thepackage.json (e.g.require('your-package/package.json')).This willlikely be a breaking change.

To make the introduction of"exports" non-breaking, ensure that everypreviously supported entry point is exported. It is best to explicitly specifyentry points so that the package's public API is well-defined. For example,a project that previously exportedmain,lib,feature, and thepackage.json could use the followingpackage.exports:

{"name":"my-package","exports":{".":"./lib/index.js","./lib":"./lib/index.js","./lib/index":"./lib/index.js","./lib/index.js":"./lib/index.js","./feature":"./feature/index.js","./feature/index":"./feature/index.js","./feature/index.js":"./feature/index.js","./package.json":"./package.json"}}

Alternatively a project could choose to export entire folders both with andwithout extensioned subpaths using export patterns:

{"name":"my-package","exports":{".":"./lib/index.js","./lib":"./lib/index.js","./lib/*":"./lib/*.js","./lib/*.js":"./lib/*.js","./feature":"./feature/index.js","./feature/*":"./feature/*.js","./feature/*.js":"./feature/*.js","./package.json":"./package.json"}}

With the above providing backwards-compatibility for any minor package versions,a future major change for the package can then properly restrict the exportsto only the specific feature exports exposed:

{"name":"my-package","exports":{".":"./lib/index.js","./feature/*.js":"./feature/*.js","./feature/internal/*":null}}

Main entry point export#

When writing a new package, it is recommended to use the"exports" field:

{"exports":"./index.js"}

When the"exports" field is defined, all subpaths of the package areencapsulated and no longer available to importers. For example,require('pkg/subpath.js') throws anERR_PACKAGE_PATH_NOT_EXPORTEDerror.

This encapsulation of exports provides more reliable guaranteesabout package interfaces for tools and when handling semver upgrades for apackage. It is not a strong encapsulation since a direct require of anyabsolute subpath of the package such asrequire('/path/to/node_modules/pkg/subpath.js') will still loadsubpath.js.

All currently supported versions of Node.js and modern build tools support the"exports" field. For projects using an older version of Node.js or a relatedbuild tool, compatibility can be achieved by including the"main" fieldalongside"exports" pointing to the same module:

{"main":"./index.js","exports":"./index.js"}

Subpath exports#

Added in: v12.7.0

When using the"exports" field, custom subpaths can be defined alongwith the main entry point by treating the main entry point as the"." subpath:

{"exports":{".":"./index.js","./submodule.js":"./src/submodule.js"}}

Now only the defined subpath in"exports" can be imported by a consumer:

import submodulefrom'es-module-package/submodule.js';// Loads ./node_modules/es-module-package/src/submodule.js

While other subpaths will error:

import submodulefrom'es-module-package/private-module.js';// Throws ERR_PACKAGE_PATH_NOT_EXPORTED
Extensions in subpaths#

Package authors should provide either extensioned (import 'pkg/subpath.js') orextensionless (import 'pkg/subpath') subpaths in their exports. This ensuresthat there is only one subpath for each exported module so that all dependentsimport the same consistent specifier, keeping the package contract clear forconsumers and simplifying package subpath completions.

Traditionally, packages tended to use the extensionless style, which has thebenefits of readability and of masking the true path of the file within thepackage.

Withimport maps now providing a standard for package resolution in browsersand other JavaScript runtimes, using the extensionless style can result inbloated import map definitions. Explicit file extensions can avoid this issue byenabling the import map to utilize apackages folder mapping to map multiplesubpaths where possible instead of a separate map entry per package subpathexport. This also mirrors the requirement of usingthe full specifier pathin relative and absolute import specifiers.

Exports sugar#

Added in: v12.11.0

If the"." export is the only export, the"exports" field provides sugarfor this case being the direct"exports" field value.

{"exports":{".":"./index.js"}}

can be written:

{"exports":"./index.js"}

Subpath imports#

Added in: v14.6.0, v12.19.0

In addition to the"exports" field, there is a package"imports" fieldto create private mappings that only apply to import specifiers from within thepackage itself.

Entries in the"imports" field must always start with# to ensure they aredisambiguated from external package specifiers.

For example, the imports field can be used to gain the benefits of conditionalexports for internal modules:

// package.json{"imports":{"#dep":{"node":"dep-node-native","default":"./dep-polyfill.js"}},"dependencies":{"dep-node-native":"^1.0.0"}}

whereimport '#dep' does not get the resolution of the external packagedep-node-native (including its exports in turn), and instead gets the localfile./dep-polyfill.js relative to the package in other environments.

Unlike the"exports" field, the"imports" field permits mapping to externalpackages.

The resolution rules for the imports field are otherwise analogous to theexports field.

Subpath patterns#

History
VersionChanges
v16.10.0, v14.19.0

Support pattern trailers in "imports" field.

v16.9.0, v14.19.0

Support pattern trailers.

v14.13.0, v12.20.0

Added in: v14.13.0, v12.20.0

For packages with a small number of exports or imports, we recommendexplicitly listing each exports subpath entry. But for packages that havelarge numbers of subpaths, this might causepackage.json bloat andmaintenance issues.

For these use cases, subpath export patterns can be used instead:

// ./node_modules/es-module-package/package.json{"exports":{"./features/*.js":"./src/features/*.js"},"imports":{"#internal/*.js":"./src/internal/*.js"}}

* maps expose nested subpaths as it is a string replacement syntaxonly.

All instances of* on the right hand side will then be replaced with thisvalue, including if it contains any/ separators.

import featureXfrom'es-module-package/features/x.js';// Loads ./node_modules/es-module-package/src/features/x.jsimport featureYfrom'es-module-package/features/y/y.js';// Loads ./node_modules/es-module-package/src/features/y/y.jsimport internalZfrom'#internal/z.js';// Loads ./node_modules/es-module-package/src/internal/z.js

This is a direct static matching and replacement without any special handlingfor file extensions. Including the"*.js" on both sides of the mappingrestricts the exposed package exports to only JS files.

The property of exports being statically enumerable is maintained with exportspatterns since the individual exports for a package can be determined bytreating the right hand side target pattern as a** glob against the list offiles within the package. Becausenode_modules paths are forbidden in exportstargets, this expansion is dependent on only the files of the package itself.

To exclude private subfolders from patterns,null targets can be used:

// ./node_modules/es-module-package/package.json{"exports":{"./features/*.js":"./src/features/*.js","./features/private-internal/*":null}}
import featureInternalfrom'es-module-package/features/private-internal/m.js';// Throws: ERR_PACKAGE_PATH_NOT_EXPORTEDimport featureXfrom'es-module-package/features/x.js';// Loads ./node_modules/es-module-package/src/features/x.js

Conditional exports#

History
VersionChanges
v13.7.0, v12.16.0

Unflag conditional exports.

v13.2.0, v12.16.0

Added in: v13.2.0, v12.16.0

Conditional exports provide a way to map to different paths depending oncertain conditions. They are supported for both CommonJS and ES module imports.

For example, a package that wants to provide different ES module exports forrequire() andimport can be written:

// package.json{"exports":{"import":"./index-module.js","require":"./index-require.cjs"},"type":"module"}

Node.js implements the following conditions, listed in order from mostspecific to least specific as conditions should be defined:

  • "node-addons" - similar to"node" and matches for any Node.js environment.This condition can be used to provide an entry point which uses native C++addons as opposed to an entry point which is more universal and doesn't relyon native addons. This condition can be disabled via the--no-addons flag.
  • "node" - matches for any Node.js environment. Can be a CommonJS or ESmodule file.In most cases explicitly calling out the Node.js platform isnot necessary.
  • "import" - matches when the package is loaded viaimport orimport(), or via any top-level import or resolve operation by theECMAScript module loader. Applies regardless of the module format of thetarget file.Always mutually exclusive with"require".
  • "require" - matches when the package is loaded viarequire(). Thereferenced file should be loadable withrequire() although the conditionmatches regardless of the module format of the target file. Expectedformats include CommonJS, JSON, native addons, and ES modules.Always mutuallyexclusive with"import".
  • "module-sync" - matches no matter the package is loaded viaimport,import() orrequire(). The format is expected to be ES modules that doesnot contain top-level await in its module graph - if it does,ERR_REQUIRE_ASYNC_MODULE will be thrown when the module isrequire()-ed.
  • "default" - the generic fallback that always matches. Can be a CommonJSor ES module file.This condition should always come last.

Within the"exports" object, key order is significant. During conditionmatching, earlier entries have higher priority and take precedence over laterentries.The general rule is that conditions should be from most specific toleast specific in object order.

Using the"import" and"require" conditions can lead to some hazards,which are further explained inthe dual CommonJS/ES module packages section.

The"node-addons" condition can be used to provide an entry point whichuses native C++ addons. However, this condition can be disabled via the--no-addons flag. When using"node-addons", it's recommended to treat"default" as an enhancement that provides a more universal entry point, e.g.using WebAssembly instead of a native addon.

Conditional exports can also be extended to exports subpaths, for example:

{"exports":{".":"./index.js","./feature.js":{"node":"./feature-node.js","default":"./feature.js"}}}

Defines a package whererequire('pkg/feature.js') andimport 'pkg/feature.js' could provide different implementations betweenNode.js and other JS environments.

When using environment branches, always include a"default" condition wherepossible. Providing a"default" condition ensures that any unknown JSenvironments are able to use this universal implementation, which helps avoidthese JS environments from having to pretend to be existing environments inorder to support packages with conditional exports. For this reason, using"node" and"default" condition branches is usually preferable to using"node" and"browser" condition branches.

Nested conditions#

In addition to direct mappings, Node.js also supports nested condition objects.

For example, to define a package that only has dual mode entry points foruse in Node.js but not the browser:

{"exports":{"node":{"import":"./feature-node.mjs","require":"./feature-node.cjs"},"default":"./feature.mjs"}}

Conditions continue to be matched in order as with flat conditions. Ifa nested condition does not have any mapping it will continue checkingthe remaining conditions of the parent condition. In this way nestedconditions behave analogously to nested JavaScriptif statements.

Resolving user conditions#

Added in: v14.9.0, v12.19.0

When running Node.js, custom user conditions can be added with the--conditions flag:

node --conditions=development index.js

which would then resolve the"development" condition in package imports andexports, while resolving the existing"node","node-addons","default","import", and"require" conditions as appropriate.

Any number of custom conditions can be set with repeat flags.

Typical conditions should only contain alphanumerical characters,using ":", "-", or "=" as separators if necessary. Anything else may runinto compability issues outside of node.

In node, conditions have very few restrictions, but specifically these include:

  1. They must contain at least one character.
  2. They cannot start with "." since they may appear in places that alsoallow relative paths.
  3. They cannot contain "," since they may be parsed as a comma-separatedlist by some CLI tools.
  4. They cannot be integer property keys like "10" since that can haveunexpected effects on property key ordering for JS objects.

Community Conditions Definitions#

Condition strings other than the"import","require","node","module-sync","node-addons" and"default" conditionsimplemented in Node.js core are ignored by default.

Other platforms may implement other conditions and user conditions can beenabled in Node.js via the--conditions /-C flag.

Since custom package conditions require clear definitions to ensure correctusage, a list of common known package conditions and their strict definitionsis provided below to assist with ecosystem coordination.

  • "types" - can be used by typing systems to resolve the typing file forthe given export.This condition should always be included first.
  • "browser" - any web browser environment.
  • "development" - can be used to define a development-only environmententry point, for example to provide additional debugging context such asbetter error messages when running in a development mode.Must always bemutually exclusive with"production".
  • "production" - can be used to define a production environment entrypoint.Must always be mutually exclusive with"development".

For other runtimes, platform-specific condition key definitions are maintainedby theWinterCG in theRuntime Keys proposal specification.

New conditions definitions may be added to this list by creating a pull requestto theNode.js documentation for this section. The requirements for listinga new condition definition here are that:

  • The definition should be clear and unambiguous for all implementers.
  • The use case for why the condition is needed should be clearly justified.
  • There should exist sufficient existing implementation usage.
  • The condition name should not conflict with another condition definition orcondition in wide usage.
  • The listing of the condition definition should provide a coordinationbenefit to the ecosystem that wouldn't otherwise be possible. For example,this would not necessarily be the case for company-specific orapplication-specific conditions.
  • The condition should be such that a Node.js user would expect it to be inNode.js core documentation. The"types" condition is a good example: Itdoesn't really belong in theRuntime Keys proposal but is a good fithere in the Node.js docs.

The above definitions may be moved to a dedicated conditions registry in duecourse.

Self-referencing a package using its name#

History
VersionChanges
v13.6.0, v12.16.0

Unflag self-referencing a package using its name.

v13.1.0, v12.16.0

Added in: v13.1.0, v12.16.0

Within a package, the values defined in the package'spackage.json"exports" field can be referenced via the package's name.For example, assuming thepackage.json is:

// package.json{"name":"a-package","exports":{".":"./index.mjs","./foo.js":"./foo.js"}}

Then any modulein that package can reference an export in the package itself:

// ./a-module.mjsimport { something }from'a-package';// Imports "something" from ./index.mjs.

Self-referencing is available only ifpackage.json has"exports", andwill allow importing only what that"exports" (in thepackage.json)allows. So the code below, given the previous package, will generate a runtimeerror:

// ./another-module.mjs// Imports "another" from ./m.mjs. Fails because// the "package.json" "exports" field// does not provide an export named "./m.mjs".import { another }from'a-package/m.mjs';

Self-referencing is also available when usingrequire, both in an ES module,and in a CommonJS one. For example, this code will also work:

// ./a-module.jsconst { something } =require('a-package/foo.js');// Loads from ./foo.js.

Finally, self-referencing also works with scoped packages. For example, thiscode will also work:

// package.json{"name":"@my/package","exports":"./index.js"}
// ./index.jsmodule.exports =42;
// ./other.jsconsole.log(require('@my/package'));
$node other.js42

Dual CommonJS/ES module packages#

Seethe package examples repository for details.

Node.jspackage.json field definitions#

This section describes the fields used by the Node.js runtime. Other tools (suchasnpm) useadditional fields which are ignored by Node.js and not documented here.

The following fields inpackage.json files are used in Node.js:

  • "name" - Relevant when using named imports within a package. Also usedby package managers as the name of the package.
  • "main" - The default module when loading the package, if exports is notspecified, and in versions of Node.js prior to the introduction of exports.
  • "type" - The package type determining whether to load.js files asCommonJS or ES modules.
  • "exports" - Package exports and conditional exports. When present,limits which submodules can be loaded from within the package.
  • "imports" - Package imports, for use by modules within the packageitself.

"name"#

History
VersionChanges
v13.6.0, v12.16.0

Remove the--experimental-resolve-self option.

v13.1.0, v12.16.0

Added in: v13.1.0, v12.16.0

{"name":"package-name"}

The"name" field defines your package's name. Publishing to thenpm registry requires a name that satisfiescertain requirements.

The"name" field can be used in addition to the"exports" field toself-reference a package using its name.

"main"#

Added in: v0.4.0
{"main":"./index.js"}

The"main" field defines the entry point of a package when imported by namevia anode_modules lookup. Its value is a path.

When a package has an"exports" field, this will take precedence over the"main" field when importing the package by name.

It also defines the script that is used when thepackage directory is loadedviarequire().

// This resolves to ./path/to/directory/index.js.require('./path/to/directory');

"type"#

History
VersionChanges
v13.2.0, v12.17.0

Unflag--experimental-modules.

v12.0.0

Added in: v12.0.0

The"type" field defines the module format that Node.js uses for all.js files that have thatpackage.json file as their nearest parent.

Files ending with.js are loaded as ES modules when the nearest parentpackage.json file contains a top-level field"type" with a value of"module".

The nearest parentpackage.json is defined as the firstpackage.json foundwhen searching in the current folder, that folder's parent, and so on upuntil a node_modules folder or the volume root is reached.

// package.json{"type":"module"}
# In same folder as preceding package.jsonnode my-app.js# Runs as ES module

If the nearest parentpackage.json lacks a"type" field, or contains"type": "commonjs",.js files are treated asCommonJS. If the volumeroot is reached and nopackage.json is found,.js files are treated asCommonJS.

import statements of.js files are treated as ES modules if the nearestparentpackage.json contains"type": "module".

// my-app.js, part of the same example as aboveimport'./startup.js';// Loaded as ES module because of package.json

Regardless of the value of the"type" field,.mjs files are always treatedas ES modules and.cjs files are always treated as CommonJS.

"exports"#

History
VersionChanges
v14.13.0, v12.20.0

Add support for"exports" patterns.

v13.7.0, v12.17.0

Unflag conditional exports.

v13.7.0, v12.16.0

Implement logical conditional exports ordering.

v13.7.0, v12.16.0

Remove the--experimental-conditional-exports option. In 12.16.0, conditional exports are still behind--experimental-modules.

v13.2.0, v12.16.0

Implement conditional exports.

v12.7.0

Added in: v12.7.0

{"exports":"./index.js"}

The"exports" field allows defining theentry points of a package whenimported by name loaded either via anode_modules lookup or aself-reference to its own name. It is supported in Node.js 12+ as analternative to the"main" that can support definingsubpath exportsandconditional exports while encapsulating internal unexported modules.

Conditional Exports can also be used within"exports" to define differentpackage entry points per environment, including whether the package isreferenced viarequire or viaimport.

All paths defined in the"exports" must be relative file URLs starting with./.

"imports"#

Added in: v14.6.0, v12.19.0
// package.json{"imports":{"#dep":{"node":"dep-node-native","default":"./dep-polyfill.js"}},"dependencies":{"dep-node-native":"^1.0.0"}}

Entries in the imports field must be strings starting with#.

Package imports permit mapping to external packages.

This field definessubpath imports for the current package.