Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider dual CJS/ESM export #169

Open
mcollina opened this issue Sep 21, 2021 · 17 comments
Open

Consider dual CJS/ESM export #169

mcollina opened this issue Sep 21, 2021 · 17 comments

Comments

@mcollina
Copy link

ESM is not ready for prime time in a significant part of the Node.js usage needs the stabilization of Loaders, which are still experimental and prone to changes. Therefore I'm not ready switching my modules to be ESM-only.

Would you consider dual publishing for this module?

@chase-manning
Copy link
Collaborator

Oh great idea! Would be keen to do this 😄
I don't know how to though ha ha, if it's easy could you raise a PR?
Otherwise I'll do some investigating and see if I can work it out 😄

@mcollina
Copy link
Author

@kibertoad maybe could you help?

@kibertoad
Copy link

@chase-manning Does https://github.com/ai/dual-publish/ look like a suitable solution for you?

@chase-manning
Copy link
Collaborator

Oh yes thanks that looks like a good solution!

@mcollina
Copy link
Author

Note that it would change

import dateFormat from "dateformat";

to

import { dateFormat } from "dateformat";

What's the problem with webpack and default exports @kibertoad ?

@kibertoad
Copy link

@mcollina Problem is this: webpack/webpack#6584
From my understanding it is mostly addressed in Webpack 5: webpack/webpack#7973 (comment)

@mcollina
Copy link
Author

Ok thanks

@chaeron
Copy link

chaeron commented Sep 30, 2021

The problem with this approach is that existing code that uses dataformat and CJS requires will have to change to use:

import { dateFormat } from "dateformat";

instead of

import dateFormat from "dateformat";

That is a huge headache for those of us that use dateformat extensively.

I would prefer to see two separate npm packages:

  • dateformat: the existing CJS module using existing require syntax
  • dateformat-esm: the new ESM version that requires imports instead of requires

That allows users to pick when they want to migrate over to the new ESM module, and in the meantime won't break existing code bases that depend on dateformat.

And yeah....this requires (all puns intended) more work on the part of the module maintainer.

@brookmg
Copy link

brookmg commented Oct 1, 2021

If anyone else is having a similar problem, check out https://github.com/knowledgecode/date-and-time. it supports common js but has some formatting different from this module. I am not in any way affiliated with the project only sharing it because it solved my problem.

@kibertoad
Copy link

kibertoad commented Oct 1, 2021

The problem with this approach is that existing code that uses dataformat and CJS requires will have to change

If released as a semver major, how is that an issue?

@chase-manning
Copy link
Collaborator

Hey @jimmywarting what's your take on this issue? 😄

@jimmywarting
Copy link
Contributor

jimmywarting commented Oct 1, 2021

I say go for ESM only. @sindresorhus is converting all of his 1000+ packages, node-fetch and submodules use esm-only, LinusU is switching to ESM-only as well whenever he touch a own commonjs project of his. WebTorrent and all sub-modules is also in the process of being converted to ESM-only. And from the looks of it Babel 8 is also going to become esm only
There is no doubt that esm is the feature and more and more is converting to ESM to support both Deno and Browser imports without a bundler or npm package. Every project i own is also converted to esm only

I think maintaining a dual package support is a #developer-pain. it duplicates all the files and package size. it introduces bundlers/compilers (and this dose not apply to node-dateformat but compiling everything into one cjs file means you would have instanceof problems with other dependencies if multiple packages uses the same dependencies)

I think those who are stuck with cjs can use the previous major version and pin it to v4. That's what a semantic Major breaking change means... Don't update it if you are not ready for it.

while reading pinojs/pino-pretty#235 i would hate for packages to be divided up by diffrent forks (cjs vs esm) where there are no longer one single source of truth. it would be grate if the main upstream repo got all the updates.

There are still ways after all to load esm only packages using the async import() available from cjs after all.

ESM have been out for a long time and it's marked as stable https://nodejs.org/api/esm.html
@mcollina you talk about Loaders that are experimental, do you need something that can "resolve" stuff?

I really think NodeJS should do something about this split war between cjs and esm

  • support top level await in commonjs so folks can use async import()
  • or support require(esm) in a sync (blocking) way
  • support converting any async into sync by blocking something via a util function (it have also been suggested in some issue i can't find)
  • start discouraging cjs from new projects and marking cjs as legacy, the more ppl that create cjs project the more problem they will have to update to esm in the feature
    I also think npm and yarn should start defaulting with "type": "module" in package.json

But i don't think i have a much saying in this as i'm just a user that have contributed to the project. I don't consider myself a Collaborator or a member of this project. If you want to support dual packages, then go for it, it's up to you.

@jsumners
Copy link

jsumners commented Oct 1, 2021

I think those who are stuck with cjs can use the previous major version and pin it to v4. That's what a semantic Major breaking change means... Don't update it if you are not ready for it.

Nonsense. That means no security fixes because it adds more complicated developer maintenance that isn't going to be done. This is the response of people who do not maintain a large production ecosystem.

There are still ways after all to load esm only packages using the async import() available from cjs after all.

None that don't require users to refactor their code into a big pile of promises.

  • support top level await in commonjs

Impossible.

Likely also impossible due to ESM spec.

  • start discouraging cjs from new projects and marking cjs as legacy, the more ppl that create cjs project the more problem they will have to update to esm in the feature

Again, this is the response of people who do not maintain large production ecosystems. Even if everything else would be viable (e.g. the budget to convert everything to a completely different paradigm were actually possible for anyone), the fact that ESM is not able to be instrumented means actual business cannot "just make the switch."

Yes, semver major implies breaking changes. But we will disagree all day long that it includes completely changing the module contract. That's the realm of a new module with a new name. Don't care who is doing it.

@chaeron
Copy link

chaeron commented Oct 1, 2021

I'm with @jsumners on this one....well said James!

The whole CommonJS vs ESM module thing is a huge stinking mess and the horns of a serious dilemma for those of us that have a large production code base to maintain and extend.

@itsHusky
Copy link

itsHusky commented Oct 1, 2021

I am not too sure if this is addressed in the right topic, but I wasn't able to use version 5.0.1, as the module.exports statement is missing in that version. So, I went back to version 4.6.3, which worked for me. I just wondered, as the ReadMe still says: Added a module.exports = dateFormat; statement at the bottom. Version 5.0.1 does not seem to have the module.exports statement anymore.

import dateFormat from "dateformat";
gave me the following error :

ParseError: 'import' and 'export' may appear only with 'sourceType: module'

I use TypeScript and bundle modules with browserify.

@jsumners
Copy link

jsumners commented Oct 1, 2021

I am not too sure if this is addressed in the right topic, but I wasn't able to use version 5.0.1, as the module.exports statement is missing in that version. So, I went back to version 4.6.3, which worked for me. I just wondered, as the ReadMe still says: Added a module.exports = dateFormat; statement at the bottom. Version 5.0.1 does not seem to have the module.exports statement anymore.

import dateFormat from "dateformat"; gave me the following error :

ParseError: 'import' and 'export' may appear only with 'sourceType: module'

I use TypeScript and bundle modules with browserify.

No. This seems completely off topic and should be a new issue.

@BasilaryGroup
Copy link

If anyone else is having a similar problem, check out https://github.com/knowledgecode/date-and-time. it supports common js but has some formatting different from this module. I am not in any way affiliated with the project only sharing it because it solved my problem.

Thanks. We just ported our nodejs apps to https://github.com/knowledgecode/date-and-time. It was simple to do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants