Skip to content

Create doc on how to support ESM and CommonJS when publishing modules #542

Closed

Description

@mhdawson

From discussion at the last collaborator summit.

This would help as the suggestion was that there were some easy ways to do this.

Activity

  1. ljharb commented on Oct 12, 2022

    @ljharb
    SponsorMember

    Given that by far the easiest way is “only publish CJS”, and if you want named exports, “publish CJS transpiled from ESM” - what more would go in this document?

  2. lemanschik commented on Nov 27, 2022

    @lemanschik
  3. ljharb commented on Nov 27, 2022

    @ljharb
    SponsorMember

    @lemanschik i strongly disagree with that; a default export is what a module is; named exports are what module has, and most modules should be something. That’s a stylistic choice and not something node should be weighing in on. I, and the Airbnb style guide ftr, say that you should almost always do module.exports = function.

  4. lemanschik commented on Nov 27, 2022

    @lemanschik
  5. ljharb commented on Nov 27, 2022

    @ljharb
    SponsorMember

    I have a number of projects that work perfectly compatibly with a build process, so I’m not sure about those reports.

  6. lemanschik commented on Nov 27, 2022

    @lemanschik
  7. lemanschik commented on Nov 28, 2022

    @lemanschik
  8. lemanschik commented on Nov 28, 2022

    @lemanschik
  9. lemanschik commented on Nov 28, 2022

    @lemanschik
  10. lemanschik commented on Nov 28, 2022

    @lemanschik
  11. lemanschik commented on Nov 28, 2022

    @lemanschik
  12. lemanschik commented on Nov 29, 2022

    @lemanschik
  13. ljharb commented on Nov 29, 2022

    @ljharb
    SponsorMember

    What is the benefit of doing all this when “just CJS” works everywhere?

  14. lemanschik commented on Nov 29, 2022

    @lemanschik
    Contributor

    @ljharb i am happy that you ask for example it makes total new forms of builds more enjoyable and compose able at present we have overall good results with opening component based ipc specifiers inside chromium and v8 it self. this leads to stuff like running the monaco editor as chrome extension directly then using workspaces and overrides and then directly use unmodified directly loaded modules out of the npm ecosystem in a way that i can patch and replace them or use single functions of them to compose something total diffrent

    It is simply expressiv when i can write

    const reused = import('anything').then(any=> Object.assign(any, { addOrpatch }))

    and get all original source references without parsing generating and all that of tons of import maps in facts i am also working mean while on building the whole chromium platform in a browser in a virtual x86 vm running on wasm and other stuff also directly exposing remote filesystems for distributed builds via webrtc and such stuff it helps a lot if we do not need to add incremental build steps and can directly cache distributed incremental build results

    note also collabing on MESON Build system written in ECMAScript that opens up building NodeJS inside the browser distributed.

    we talk about projects with a lot of dynamic references and far more then some million well documented symbols.

  15. 17 remaining items

  16. vostrik commented on Dec 9, 2022

    @vostrik
    Member

    @lemanschik thank you so much for this detailed response.
    I've just read all of your replies including tiny book and small discussion in TS repo by links above.
    I appreciate it.

    But I also have 2 theses:

    1. I really think that it would be more effective to discuss about new module approaches in Modules Team.
    2. Main topic for this discussion is Create doc on how to support ESM and CommonJS when publishing modules. That's why we should focus on current ecosystem state and document it. Of course with simplicity criteria as u described.

    Let me repeat my suggestion:

    Can we add drafts to this issue from both opinions in format like this:

    1. Original demo JavaScript code
    2. Export notation for CJS and ESM
    3. Settings samples for popular bundlers (webpack, rollup, parcel, maybe more)
      I. e. add examples folder to our repository and 2 samples which we can test in GitHub Codespaces and discuss about it.

    @ljharb, @mhdawson tell me please, what do you think about my propose and about maybe(!) a little bit off-topic vibe from previous messages.

    P. S. @lemanschik I really appreciate your thoughts and even ready to participate in PoC of your idea if needed.

  17. lemanschik commented on Dec 10, 2022

    @lemanschik
  18. ljharb commented on Dec 10, 2022

    @ljharb
    SponsorMember

    @lemanschik can you please stop posting dozens of essays? The thread is already impossibly long to read.

  19. lemanschik commented on Dec 10, 2022

    @lemanschik
    Contributor

    execution strategy lets move npm it self into the browser via replacing the nativ parts with esm implementations something that is easy replace able it does only need filesystem it should need nothing more

  20. ljharb commented on Dec 10, 2022

    @ljharb
    SponsorMember

    That’s not likely to happen, and either way it’s entirely off topic for this thread.

    This is about documenting what is, not trying to imagine a different reality.

  21. lemanschik commented on Dec 10, 2022

    @lemanschik
    Contributor

    @ljharb that is the current case but no one uses it please bring up blockers.

  22. mhdawson commented on Jan 19, 2023

    @mhdawson
    MemberAuthor
  23. lholmquist commented on Jun 4, 2024

    @lholmquist
    Contributor

    Found this on the node.js docs: https://nodejs.org/api/packages.html#dual-commonjses-module-packages

    Does this cover what we wanted?

  24. frank-dspeed commented on Jun 5, 2024

    @frank-dspeed
    Contributor

    @lholmquist it was not what we search for but it is today maybe the thing we search for let me explain:

    Out of Historical Reason there where 1x Export per Package JSON then later with es2015 the package json got the import / export field which can store multiple exports.

    This exports have also support for nested conditional exports thats the part that your posting.

    So the Field is only supported by current tooling every tooling today supports them as far as i know. If not support can be added in less then a day.

    the --condition flag lets you choose one set of imports/exports.

    Also i can announce the landing of require esm inside NodeJS 22+

    require('es-module.js')

    works under a flag if the ESM does not contain top level await at last.

  25. lemanschik commented on Jul 2, 2024

    @lemanschik
    Contributor

    I would propose the following path forward now:

    • Create ESM-only packages and only use the module field. Call it a day.
    • Use the -r esm flag to require the ESM NPM module to activate user-land support for require(esm-module.js) with additional support for top-level await as a migration path.
    • From Node.js 22+ onward, migrate to --experimental-require-module and -r esm until the other flag works.
    • From Node.js 22.x+ when the experimental flag gets an opt-out flag, call it a day. We will have resolved the ambiguity. Top-level import can import ESM and CJS code, and require can do the same. While everything should get transpiled to ESM for analyzability and tooling.
    • should annoy people to produce only exports["string"] = assignments and do avoid module.exports as migration path also exports.name = any is total ok simple let them avoid module.exports = and we wre good to go

    Special edge case electron and other runtimes consuming npm

    There are cases where .cjs is needed they will simple need to create a cjs entrypoint inside that single application where they use the modules they should not publish that application but if they wish to publish it then they simple publish it with a post install transpil to cjs hook or again use the -r esm flag

    ESM -r esm as migration path is green for

    • nwjs
    • electron
    • node-ts
    • tsc / typescript
  26. AugustinMauroy commented on Jan 11, 2025

    @AugustinMauroy
    Member
  27. added
    articleNeed to spread this information
    and removed on Jan 7, 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

    articleNeed to spread this information

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions