npm / node-semver

The semver parser for node (the one npm uses)
ISC License
5.09k stars 492 forks source link

[ENHANCEMENT] Publish package as standard JS modules #712

Open justinfagnani opened 5 months ago

justinfagnani commented 5 months ago

Is there an existing issue for this?

Current Behavior

This package is currently published as CommonJS modules only. This makes it impossible to use in browsers and other environments that don't support Common JS, without a build step.

Expected Behavior

This should just work with a suitable import map:

import semver from 'semver';

This could be done as part of a migration to standard JS modules only, or a dual-mode package, possibly as part of https://github.com/npm/node-semver/issues/498

Steps To Reproduce

  1. In a browser
  2. With dev server that can rewrite bare module specifiers to URLs (such as @web/dev-server with the --node-resolve flag)
  3. Load a module script with import semver from 'semver';
  4. See error...

Environment

ljharb commented 5 months ago

I’d hope an ESM-only migration is out of the question, since that would make semver unusable for the vast majority of ecosystem users.

SebastianBock83 commented 5 months ago

With version 5.0 the minified browser useable file was removed. That means 4.3.6 is the last version where the minified browser usable files are available.

4.3.6 and several other version until 7.5.2 have a known CVE issue inside. https://nvd.nist.gov/vuln/detail/CVE-2022-25883

Is there any possibility that a new version of semver contain the minified browser version again or at least some kind of build script, to build the browser version again.

Best Regards, Sebastian

ljharb commented 5 months ago

@SebastianBock83 why can't you build it yourself, locally, to use in whatever format you need?

SebastianBock83 commented 5 months ago

@SebastianBock83 why can't you build it yourself, locally, to use in whatever format you need?

The project where the lib is used is a quite "old" implementation without the usage of modules and any kind of build environment. Pure JavaScript and HTML with script tags.

Rework to a module / build version would of course be possible but would take time and ressources. The question is just for decision making.

Or is there any easy way to build the minified browser useable file via a script / library? If this is a general procedure and I am lacking of knowledge, sorry for the question. In case this is not the right place for that question, is there any possibility of having a private discussion out of this issue?

Best Regards, Sebastian

ljharb commented 5 months ago

To clarify, I'm not asking why you don't convert to a modern workflow, I'm asking why you can't use node locally to make a dist file, and vendor that in your repo manually. In other words, yes, there's lots of easy ways to make a minified browser-usable file yourself, containing any number of npm packages. A package should never need to provide a pre-built file for you to use it in this way.

Feel free to find me on Twitter or Slack or Discord, or just look on StackOverflow, if you need more help with this.

SebastianBock83 commented 5 months ago

Thanks for clarification. I will check on my own - just a lack of knowledge from my side. I will contact you if necessary.

Best Regards

Hyperkid123 commented 4 months ago

Hello.

There are other questions, such as tree shaking. It can be challenging with commonjs modules and bundles like webpack or rollup. Having es module variant of the library (alongside others) will help with that.

I realize that would introduce additional dependencies in the form of some transpiler like babel which is always somewhat controversial. But now with native support of the es module in node.js or browsers, I'd seriously consider adding module output. Not just because tree shaking, but because of the environment in general.

ljharb commented 4 months ago

@Hyperkid123 you don't need treeshaking if you deep import the files you need, and CJS is identically treeshakeable as ESM from a technical standpoint.

Hyperkid123 commented 4 months ago

you don't need treeshaking if you deep import the files you need,

I am aware of that. I'll bet any amount of money that a lot of people do not.

and CJS is identically treeshakeable as ESM from a technical standpoint

Yes but in reality this does not happen. Specifically when bundlers/transpilers are used. And they are everywhere these days. I can provide a sample repo if necessary.

ljharb commented 4 months ago

Then it sounds like the best solution is to remove the barrel file in a major, and force deep imports, rather than add a build process?

SimonAlling commented 4 months ago

Then it sounds like the best solution is to remove the barrel file in a major, and force deep imports, rather than add a build process?

That might very well be the case for the tree shaking problem mentioned by @Hyperkid123.

But it doesn't address the problem of being able to use this library in non-Node contexts (where require is not defined). I'm not saying it's easy to solve that problem — it definitely isn't — but I believe that's a perfectly reasonable use case that should be considered.

If it's not feasible to adapt the package, do you perhaps know of a workaround to be able to use it in an ESM context?

ljharb commented 4 months ago

That use case has been addressed by bundlers for well over a decade (also, you can import CJS modules in node perfectly fine). If you're trying to use it in a browser ESM context (which is slower at runtime than bundling to Script, btw), or in something like Deno or Cloudflare Workers, then I believe you can use any of the bundlers out there to provide an ESM module for a package that isn't using node-specific capabilities.

SimonAlling commented 4 months ago

@ljharb: For reference, this was how I ran into the problem:

  1. Added semver as a dependency.
  2. Wrote the TypeScript code that used semver until it compiled and I was happy with it. If it compiles, it works, right? ¯\_(ツ)_/¯
  3. Ran my @web/test-runner-based test suite, which failed with ReferenceError: require is not defined.

I don't know if or how I can use a bundler to solve that. And it would have to be solved for when I build my package as well, not just for the test suite. And I would also need to know that it's acceptable for me to publish bundled code.

So it really would be super-nice if this package were available as ESM in addition to CJS. I'm painfully aware of how non-trivial it is to make that happen and the caveats entailed by it; I'm just saying it would be useful. 😊