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

module: expose CJS named-exports detection (cjs-module-lexer equivalent) #63123

Description

@SimenB

What is the problem this feature will solve?

When loading a CJS module from ESM (import {foo} from './bar.cjs'), the named exports have to be derived statically before the CJS body runs - ESM bindings need to exist at link time. Node already does this internally for require(esm) and friends, using cjs-module-lexer to lex the CJS source.

Frameworks doing the same job - Jest, and likely others wrapping CJS as ESM in custom contexts - currently take a direct dependency on the cjs-module-lexer npm package and call it themselves. Works fine, but it's redundant: every framework re-vendors a parser that Node already runs, and parsing happens twice for the same source whenever Node and the framework both touch it.

What is the feature you are proposing to solve the problem?

Some way to ask Node to do the lex for us. Two shapes that would both work:

  • module.cjsNamedExports(source: string | Buffer): string[] - pure helper, takes source, returns names.
  • SyntheticModule.fromCjsExports(exports: object, options): SyntheticModule - higher-level convenience that does both the lex and the synthetic construction.

Either shape lets frameworks delete the explicit cjs-module-lexer dependency and lean on whatever Node ships. The first is more flexible (callers may want to combine the lexed names with runtime Object.keys, which is what Jest does today to handle Object.assign patterns the lexer can miss); the second is more ergonomic if the only use case is "wrap this CJS as ESM.". Both might make sense as well, but I understand the second one might feel out of scope 🙂

What alternatives have you considered?

The current approach is the alternative: depending directly on cjs-module-lexer. There's a real tradeoff worth flagging here, though.

The npm package versions independently of Node. Bug fixes ship to users regardless of which Node version they're running. If the lexer moves into Node's surface, users get whatever lexer ships with their Node version - older Node releases would lock users to older lexer behavior, including known bugs, until they upgrade Node itself.

So I think the question isn't strictly "should Node expose this" but "is exposing it a net win given the versioning tradeoff." Possible answers:

  • Leave it as-is. Frameworks keep their npm dep; bug fixes stay decoupled from Node
  • Expose it and document the tradeoff. Frameworks that prefer always-current can keep the npm dep; frameworks that prefer not-revendoring can use the Node API and accept the version coupling

I lean toward the second - the documented choice - but happy for that to be wrong.

Activity

  1. added
    moduleIssues and PRs related to the module subsystem.
    loadersIssues and PRs related to ES module loaders.
    on May 5, 2026
  2. absidue commented on May 6, 2026

    @absidue

    Node.js doesn't actually use cjs-module-lexer anymore, it switched to the native C++ merve lexer in releases 25.6.1 and 24.14.0. Just noting that in case it makes a difference in terms of API design or behaviour.

  3. SimenB commented on May 6, 2026

    @SimenB
    MemberAuthor

    Oh, that's interesting! I missed that. In that case this ask is more relevant again and my point about getting fixes not in node is irrelevant

  4. AugustinMauroy commented on May 7, 2026

    @AugustinMauroy
    Member

    also the package is publish to npm so you can just use it https://www.npmjs.com/package/cjs-module-lexer

  5. SimenB commented on May 7, 2026

    @SimenB
    MemberAuthor

    I know - that's what we do today, like mentioned in the OP

    The current approach is the alternative: depending directly on cjs-module-lexer.

    But if Node doesn't even use it anymore I don't think that's a good alternative anymore

  6. AugustinMauroy commented on May 7, 2026

    @AugustinMauroy
    Member

    I know - that's what we do today, like mentioned in the OP

    The current approach is the alternative: depending directly on cjs-module-lexer.

    But if Node doesn't even use it anymore I don't think that's a good alternative anymore

    as my knowledge merve doesn't have node binding or wasm build. So yeah expose this api make sense

  7. github-actions commented on Aug 6, 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.

  8. added
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Aug 6, 2026
  9. github-actions commented on Sep 6, 2026

    @github-actions
    Contributor

    This issue has been automatically closed after 30 days of inactivity following its stale status (no activity for a total of 120 days).
    If this is still relevant, feel free to reopen it or leave a comment with additional details so we can continue the discussion.

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

    feature requestIssues requesting new Node.js features.loadersIssues and PRs related to ES module loaders.moduleIssues and PRs related to the module subsystem.staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions