developit / microbundle

📦 Zero-configuration bundler for tiny modules.
https://npm.im/microbundle
MIT License
8.06k stars 362 forks source link

Should `modern` option be orthogonal to module format? #618

Closed cowboyd closed 4 years ago

cowboyd commented 4 years ago

We recently decided that we wanted to drop support for older browsers and move to not transpiling generators and async/await. Our problem is that (using the recently released 0.12) we can't seem to generate a modern JavaScript that is transpiled to both commonjs and esm, and it's unclear whether it is possible to do this with microbundle today.

Given the churn around #518 #582 #570 and what is hopefully the final fix with #605 it has me wondering if things would be simpler both internally and externally if "modernity" were treated as type of content rather than a module format.

In other words, the module format could vary independently of the transpilation target. That way you could run something like:

$ microbundle -f esm,umd,cjs --target modern,es5

And microbundle would emit a matrix of modules crossed by content type and module format such as:

my-package.modern.esm.js
my-package.es5.esm.js
my-package.modern.umd.js
my-package.es5.umd.js
my-package.modern.cjs.js
my-package.es5.cjs.js

This would give package maintainers the ability to target modernity (or lack thereof) and be able to deliver easily regardless of the consumer's preferred module format.

developit commented 4 years ago

Hi Charles - just a foreword, this reply got a little long. My apologies in advance! In terms of a straightforward answer to your petition, you can actually already use a browserslist key in package.json or a .browserslistrc file to specify your browser/node support target. It governs the syntax output in all files except .modern.js (which in your description you would actually want to disable).

Now, on to the underlying question: how can we publish modern code to npm without breaking everything?

FWIW, unless you're specifically targeting only Node.js, publishing a package as modern-only is going to create a lot of confusion. Create React App transpiles node_modules by default, but no other popular bundler configurations do - that means most projects simply aren't set up to handle modern code in npm packages.

That's not to say I don't want to fix the whole "modern npm packages" issue - very much the opposite. I believe there is a way forward, but from both my own experience and in talking to the folks who maintain downstream tooling, publishing modern-only browser packages isn't going to get us there. Instead, I think we may be in a position to standardize on the existence of an Export Map as the indicator that a package provides modern code. Because Export Maps have a designated mechanism for falling back to the package.json main field, they can also be used to fall back to ES5.

However, there's a huge missing piece. In all of these approaches, from modern-only packages to backwards-compatible multi-mode packages, the syntax we refer to as "modern" is an arbitrary point-in-time decision that happens on a per-package basis. Scale that up to the whole ecosystem and we end up having no way to know if a package is ES3 or ES2020 - bad for performance, and potentially impossible to work with. The "modern" name used by Microbundle refers to "the JavaScript syntax supported in all browsers that implement Githubissues.

  • Githubissues is a development platform for aggregating issues.