镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Recommend node/default conditions instead of require/import as a solution to the dual package hazard #52174

Description

@nicolo-ribaudo

Affected URL(s)

https://nodejs.org/api/packages.html#dual-package-hazard

Description of the problem

Publishing packages with dual CommonJS and ESM sources, while has the benefits of supporting both CJS consumers and ESM-only platforms, is known to cause problems because Node.js might load both versions. Example:

package.json foo.cjs foo.mjs
{
  "name": "foo",
  "exports": {
    "require": "./foo.cjs",
    "import": "./foo.mjs"
  }
}
exports.object = {};     
export const object = {};     
package.json bar.js
{
  "name": "bar",
  "main": "./bar.js"
}
const foo = require("foo");
exports.object = foo.object;     
// my app

import { object as fooObj } from "foo";
import { object as barObj } from "bar";

console.log(fooObj === barObj); // false?????

The two suggested solutions boil down to "even when you have an ESM entrypoint, still use only CJS internallly". This solves the dual package hazard, but completely defeats the cross-platform benefits of dual modules.

If foo instead used these export conditions:

{
  "name": "foo",
  "exports": {
    "node": "./foo.cjs",
    "default": "./foo.mjs"
  }
}

Then:

  • there would be no dual-package hazard in Node.js, because it only ever loads the CommonJS version
  • there would be no dual-package hazard in bundlers, because they would only ever load either the node version (if they are configured to target Node.js) or the default version (if they are configured to target other platforms).
  • the package solves the dual-package hazard while still providing an ESM-only version

We have been using this node/default pattern in @babel/runtime for a couple years, because we wanted to provide an ESM-only version for browsers while still avoiding the dual-package hazard (@babel/runtime is mostly stateless, but @babel/runtime/helpers/temporalUndefined relies on object identity of an object defined in a separate file).

Activity

  1. added
    docIssues and PRs related to Node.js documentation.
    on Mar 21, 2024
  2. joyeecheung commented on Apr 11, 2024

    @joyeecheung
    Member

    Looks like a good first issue. Relevant file is https://github.com/nodejs/node/blob/main/doc/api/packages.md

  3. eliphazbouye commented on Apr 26, 2024

    @eliphazbouye
    Contributor

    @joyeecheung , @nicolo-ribaudo this issue is still relevant ?

  4. joyeecheung commented on Apr 26, 2024

    @joyeecheung
    Member

    Yes, IMO the doc can still be improved as suggested in the OP.

  5. mewssix commented on May 19, 2024

    @mewssix

    Is there still work to be done here?

  6. joyeecheung commented on Sep 1, 2024

    @joyeecheung
    Member

    In #54648 which adds a new pattern I realize that it just doesn't seem appropriate to document them this way in the API docs. To quote my comments:

    1. It teaches opinionated practices that some consider dangerous
    2. It will soon be obsolete when we unflag --experimental-require-module.
    3. It's difficult to understand a multi-file structure via long texts and snippets in a (rendered) markdown document.

    I think they should just be placed in their own example repo with some notes on pros/cons and maybe links to threads of discussions. But anyway API docs is the wrong place for them.

  7. B4nan commented on Sep 4, 2024

    @B4nan

    It will soon be obsolete when we unflag --experimental-require-module.

    May I ask if there is some schedule for unflagging this? Given the node 22 LTS is nearby, any chance it would happen with that version already?

  8. tats-u commented on Feb 12, 2025

    @tats-u

    "module-sync" must exist above "node" (or "require") if applicable.

    {
      "name": "foo",
      "exports": {
        "module-sync": "./foo.mjs",
        "node": "./foo.cjs",
        "default": "./foo.mjs"
      }
    }
  9. ajeeth-asperand commented on Nov 27, 2025

    @ajeeth-asperand

    Hi, I’d like to work on this issue as my first documentation contribution. Is it still available?

  10. zhanglinqian commented on Feb 12, 2026

    @zhanglinqian

    I'd like to work on this issue.

  11. Bikram-pal commented on Mar 16, 2026

    @Bikram-pal

    Hi, I’m a new contributor and would like to help with documentation improvements.
    Is there still any work needed for this issue, or should new contributions target a different repository?

  12. roshanraj9136 commented on Apr 4, 2026

    @roshanraj9136

    can i go for it?

  13. MikeMcC399 commented on Apr 7, 2026

    @MikeMcC399
    Contributor

    @joyeecheung

    Should this issue still be open, given your comments in #52174 (comment) and creation of the https://github.com/nodejs/package-examples repo?

    It's also labeled with good first issue Issues that are suitable for first-time contributors. .
    Edit: label removed Jul 21, 2026
    New contributors are still attempting to resolve it.

  14. github-actions commented on Jul 20, 2026

    @github-actions
    Contributor

    This issue has been marked as stale due to 90 days of inactivity.
    It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.

  15. added
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Jul 20, 2026
  16. tats-u commented on Jul 20, 2026

    @tats-u

    Not stale

  17. removed
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Jul 21, 2026
  18. removed
    good first issueIssues that are suitable for first-time contributors.
    on Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    docIssues and PRs related to Node.js documentation.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions