Stability: 1 - Experimental

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

    For example, a package that wants to provide different ES module exports for require() and import can be written:

    1. // package.json
    2. {
    3. "main": "./main-require.cjs",
    4. "exports": {
    5. "import": "./main-module.js",
    6. "require": "./main-require.cjs"
    7. },
    8. "type": "module"
    9. }

    Node.js supports the following conditions out of the box:

    • "import" - matches when the package is loaded via import or import(), or via any top-level import or resolve operation by the ECMAScript module loader. Applies regardless of the module format of the target file. Always mutually exclusive with "require".
    • "require" - matches when the package is loaded via require(). The referenced file should be loadable with require() although the condition matches regardless of the module format of the target file. Expected formats include CommonJS, JSON, and native addons but not ES modules as require() doesn’t support them. Always mutually exclusive with "import".
    • "node" - matches for any Node.js environment. Can be a CommonJS or ES module file. This condition should always come after "import" or "require".
    • "default" - the generic fallback that always matches. Can be a CommonJS or ES module file. This condition should always come last.

    Within the ["exports"][] object, key order is significant. During condition matching, earlier entries have higher priority and take precedence over later entries. The general rule is that conditions should be from most specific to least specific in object order.

    Other conditions such as "browser", "electron", "deno", "react-native", etc., are unknown to Node.js, and thus ignored. Runtimes or tools other than Node.js can use them at their discretion. Further restrictions, definitions, or guidance on condition names might occur in the future.

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

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

    1. {
    2. "main": "./main.js",
    3. "exports": {
    4. ".": "./main.js",
    5. "./feature": {
    6. "node": "./feature-node.js",
    7. "default": "./feature.js"
    8. }
    9. }
    10. }

    Defines a package where require('pkg/feature') and import 'pkg/feature' could provide different implementations between Node.js and other JS environments.

    When using environment branches, always include a "default" condition where possible. Providing a "default" condition ensures that any unknown JS environments are able to use this universal implementation, which helps avoid these JS environments from having to pretend to be existing environments in order 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.