-
-
Notifications
You must be signed in to change notification settings - Fork 40
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
Add build setup (ES5 & ES6, minified & unminified) #33
base: master
Are you sure you want to change the base?
Conversation
@@ -1,4 +1,4 @@ | |||
const balanced = require('./') | |||
const balanced = require('./dist/balanced-match.js') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
node comes with native support in recent versions, I wonder if we need to add a bundler, or can just bump the major and make it an ESM only module, as @sindresorhus has recently done with many modules (eg sindresorhus/p-queue@8c7325a)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's certainly an option and sindresorhus has made a case for doing so on his blog, but I don't think moving to ESM only is the right decision for every project. For server-side libraries, sure. For projects that may run in a browser, it makes sense to continue offering an ES5 version a bit longer.
A few issues I think are worth considering:
-
The package you linked to (p-queue) is better positioned to go "ESM only" because the library requires
Promise
support. Practically speaking, this means that if the library is run in a browser it will almost certainly do so in environments that support ESM modules. -
Is this library able to run client-side? If so, then I believe the library should offer legacy-compatible code at least until MS officially ends support for IE11 (August 17, 2021).
The alternative is to force library consumers to wrestle with webpack, rollup, parcel, etc. Even if these tools are already being used in a project, they have to be (re)configured to transpile some-but-not-all dependencies in
/node_modules
to avoid accidentally accidentally shipping ES6 code in ES5 bundles when they update to ESM-only versions of a library. This is what happened to me when updatingbalance-match
to v2 in css-vars-ponyfill: I was already using babel, but it was configured to ignore files in/node_modules
. As a result, rollup+babel created an ES5 bundle that contained properly transpired code (my source) and untranspiled ES6 code (balance-match v2). See v2.4.4 no longer transpiles to pure ECMAScript 5 jhildenbiddle/css-vars-ponyfill#158 for details. -
Is this a library consumers may want to load from a CDN? If so, then I believe the library should offer minified as well as unminifed versions:
<!-- Minified UMD --> <script src="https://unpkg.com/balanced-match@3"></script>
<!-- Minified ESM --> <script type="module" src="https://unpkg.com/balanced-match@3/dist/balances-match.esm.min.js"></script>
Just my $0.02. :)
If you prefer going "ESM only", I'm happy to made those changes and update the docs accordingly. Given that previous versions of balanced-match were written in ES5, I think it's important to let consumers know that the current version requires transpilation if used in legacy environments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @juliangruber.
To add some context for the desire to provide an ES5-friendly version: css-vars-ponyfill is a library I maintain that is used primarily to make life easier for projects that are forced to support IE11. It is downloaded over 100k per week from npm and over 110m per month from just one CDN (jsdelivr). As devs we're all anxious to move past legacy browsers, but not everyone has the luxury to do so.
Happy to make changes if requested.
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For server-side libraries, sure. For projects that may run in a browser, it makes sense to continue offering an ES5 version a bit longer.
Interesting, in my experience it's the opposite. All of my client side projects are transpiled, none of my server side projects are, so I've been using ESM in the browser for a while. Is it the opposite for you?
If you were to consume and not have a bundler set up, how would you do it? Is that a realistic use case for this library?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that for "entry point" libraries, like jQuery this makes sense, but for this library I anticipate it will be consumed in conjunction with others, where then using a bundler makes a lot more sense.
Thank you for all this work on this so far, however I'm not convinced this is the right way, and am still in favor of going ESM only (if anything).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I asked for community input in https://twitter.com/juliangruber/status/1391336252096516098
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I asked for community input in https://twitter.com/juliangruber/status/1391336252096516098
The poll is interesting, but it misses the point of the PR. A better poll would be "should library authors pre-transpile distributable files to ES5 or are library consumers responsible for transpiling their dependencies to ES5?" I would expect the answer to be different for new libraries that have never offered ES5 versions versus well-established libraries that have always been ES5.
I think in 2021 there is a strong argument for moving to ES modules only, but the code in that module should still be ES5 if there is a reasonable chance it will be run in a legacy browser. Give the age and popularity of this library, I think that is a reasonable assumption.
Again, just my $0.02. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we should just move to ESM
Thanks for all this input, I'll get to it next week 👏 🙇 |
Yep. Same for me. Transpiling to ES5 for node isn't (usually) the concern. The browser is where I'm focused.
Which means you're targeting modern browsers and won't run into the issue I'm describing. I think that might be where we're getting our signals crossed. A mixture of ES5 and ES6 code won't break modern browsers that can handle both, but it will break legacy browsers that can't handle ES6.
That's exactly how I consume this library in css-vars-ponyfill, and the change from ES5 to ES6-only caused me to release a broken ES5 bundle. The same will happen to any other project that depends on balanced-match that fails to transpile their dependencies (which they shouldn't have to, IMHO) if they support legacy browsers. Consider these two versions of balanced-match and how they impact css-vars-ponyfill:
My transpilation configuration (almost) always ignores files in Using v1.0.2 with babel configured to transpile only my Using v2.0.0 with the same babel configuration, my legacy-compatible bundle contains ES5 code (transpiled from
Via a CDN, as an ES module for modern browsers or an IIFE/UMD for legacy browsers. Is this less likely that consuming via bundler? Probably, but why not let people consume the library however they see fit? But just to be clear, this PR isn't about generating different versions of balanced-match so it can be consumed via a CDN. That was just a bonus that came from implementing a bundler which made it easy to do. The real purpose of this PR is to ensure that balanced-match offers an ES5 distributable. Notice that the Hope this helps explain bit better. Apologies for the lengthy response. |
You can transpile ES6 code to ES5 code for browsers, so import isn't a deal breaker 🤔 |
Yep. I just propose that you (the library author) should do the transpilation to ES5 so your library consumers don't have to. Why? For all of the reasons stated above, but summarized because it is much easier for you to do so and the cost to you is near zero. The goal of this PR is to support all platforms (legacy and modern, node and browser), allow consumers to use the library however they see fit ( With v1, consumers could do this: // ES5 CJS ("main" in package.json)
const balanced = require('balanced-match'); With v2, consumers can do this: // ES6 CJS ("main" in package.json)
// 👎 Legacy bundles now require transpilation of node_modules
const balanced = require('balanced-match'); With this PR, consumers can do this: <!-- ES5 ESM ("module" in package.json) -->
<script type="module" src="http://my.cdn.com/balanced-match/dist/balanced-match.esm.min.js"></script>
<!-- ES5 UMD ("browser" in package.json) -->
<script src="http://my.cdn.com/balanced-match/dist/balanced-match.min.js"></script> // ES5 ESM ("module" in package.json)
import balanced from 'balanced-match';
// ES5 UMD ("main" value in package.json)
const balanced = require('balanced-match'); The main criticism of the approach above is that modern platforms are forced to use the (potentially) larger transpiled ES5 source. That is not an issue for the particular library though as the ES5 and ES6 versions are roughly the same size. So, why not just ship ES5 everywhere and make life easier for consumers? The other logical option is to deliver ES6 code as an ES module and ES5 code as a UMD. The advantage to this is that ES6-capable platforms receive ES6 code. The disadvantage is that dependents that bundle code for legacy browsers will either have to 1) // ES6 ESM ("module" in package.json)
// 👍 Modern platforms get ES6 code
// ⚠️ Legacy bundles require transpilation of node_modules when using `import`
import balanced from 'balanced-match';
// ES5 UMD ("main" value in package.json)
// 👍 No transpilation necessary for legacy bundles
// 👎 Modern platforms get ES5 code
const balanced = require('balanced-match'); Either options seems like a better alternative to the current "ES6 as CJS" approach used in balanced-match v2.x Anyway, this is a lot of back-and-forth for what I thought would be a pretty straight-forward PR. Happy to continue the discussion if you like or move on if you feel strongly about leaving things as-is. Thanks! |
fix #32
package.json
to reference distributable files (main
,module
,browser
, andunpkg
)files
field inpackage.json
to remove source and include/dist
files in package published to npm.gitignore
to accommodate changesThe end results is a new
/dist
directory with the following files:These eight files provide support for legacy and modern browser and node environments.