-
-
Notifications
You must be signed in to change notification settings - Fork 26.9k
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
Use es2015-loose Babel preset in production build #198
Comments
Lifted from #189 (comment): Loose mode generates code that is simpler, but less strictly compliant to spec. Compare output: I'm not aware of any reason to not at least run your production build in loose mode. I'm also not aware of anybody who deliberately uses non-loose mode. |
Disclaimer: everything I know about loose mode I learned from this blog post: http://www.2ality.com/2015/12/babel6-loose-mode.html That said, from that link:
Do you disagree? Also, it appears from npm stats that regular mode is about 20x as popular as loose mode. So |
These are the most prominent examples I can think of from around the React ecosystem: Redux: https://github.com/reactjs/redux/blob/v3.5.2/.babelrc#L3-L18 React: https://github.com/facebook/react/blob/v15.2.1/.babelrc#L11-L19 I'm not exaggerating when I say that I'm not aware of any packages that are intentionally not using loose mode. There might be an argument for e.g. running test suites against both loose mode and strict mode, but I'm not aware of anybody who actually does so. As far as I'm aware, almost all "real" projects just use es2015-loose, when their authors are aware of that option. |
We use loose mode inside of fb on react native |
I'm good with using loose mode. |
Same with babel itself https://github.com/babel/babel/blob/master/package.json#L50 You would think it would be the opposite; that you would want to run more spec compilant 😄, what about add-module-exports then https://github.com/59naga/babel-plugin-add-module-exports? |
We want people to use |
I've seen only one piece of code, that didn't work the same in loose mode: Code from SO answer won't give you the same in loose mode [...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-
//=> [ArrayIterator] in loose mode Similar example from - developer.mozilla.org, var arr = ["a", , "c"];
var sparseKeys = Object.keys(arr);
var denseKeys = [...arr.keys()];
console.log(sparseKeys); // ['0', '2']
console.log(denseKeys); // [0, 1, 2]
-
console.log(denseKeys); // [ArrayIterator] in loose mode |
I'd say Most non-official Babel plugins I've tried have needed a |
Right this would probably be for an application anyway and everything in here would be import/export like Dan mentioned @vladshcherbin that's because in loose mode that transpiles to
|
@hzoo yes. There should be a note somewhere that babel in production is in loose mode as this examples will work different in dev / production and especially for a novice it won't be obvious to understand what's wrong. |
If we enable loose, we enable it everywhere. Having differences between dev and prod is bad. |
Ideally I think we'd like a We cannot have different behaviour in production vs. dev (couldn't agree more on that point) but we can/should warn users in development mode. |
Are there any lint rules against things that loose does differently? |
I think mostly they can't be detected statically (in the general case) otherwise we could just have one babel config that would do the At runtime though, you could detect that something is iterable but not an array for example. |
I had an idea that it'd be cool to run tests against both I've never gone through with that idea and I haven't seen anyone do anything like it. But it's worth bringing up. Users are already eating the downsides of loose mode because all their dependencies will be using loose mode. Might as well let them have the benefits in their code too. |
My biggest concern here is that we leave apps in a state where they can't disable the babel transform even once all browsers support the features natively. We need to do what we can to discourage people relying on it being loose. I do recognise that the performance benefits of loose are to big to ignore though. |
I'm wondering, about performance benefits. This may be a very stupid comment, but as Chrome, Firefox, Safari 10 and Edge all can run ES2015 code, it sounds as a waste to me to not make use of that. For the production config, wouldn't it be more performant, to have a small script in the beginning that determines the browser and the version of the browser, and runs an ES5 bundle if it is IE or a mobile browser (or an old version of chrome,firefox,safari), and otherwise runs an native es2015 bundle? Just an idea, I may say something really stupid here. |
That's sort of the dream, but it's hard to get to. You'd need to make multiple builds, feature-sniff appropriately for a wide set of features on the client, then ship the appropriate build. But it's actually a bit worse than that, because if you really want to ship ES2015 code, you want your dependencies to expose an ES2015 build, and then figure out how to use that for your "real ES2015" build (as contrasted with It's the right thing to do, but the degree of complexity is quite high, and I'm not aware of any good tooling around even doing the more limited goal of shipping proper ES2015 code for your own application (otherwise I'd be using it). |
I have to say, humbly, that I'm completely baffled by this thread. You've clearly shown that some incredible projects, developed by really talented people, use loose mode. I'm still trying to wrap my head around why you would think that non-standard behaviour is what's best for the average user. Which do you think the average user would prefer?
The way I see it, perhaps the very talented people who work on React or Babel or other impressive projects that use loose mode, are smart enough to still be productive while working with the mental constraint of having to remember what's an ArrayIterator and what isn't and where they may use the spread operator as-is and where they may not. I'd like to argue that for the average user this is a significant constraint that should be avoided. I sincerely hope I'm not coming off as too aggressive, but there are some very smart people weighing in on this, and I find myself completely disagreeing with you. I'd really like to understand where I'm wrong, if I'm wrong. |
I think the difference is probably negligible for the use cases of most apps, and we should err on the side of no surprises. (Correct me if I’m wrong.) Libraries are a different story because they usually do a lot of work and need to be performant for everyone. So “we’d like consistent ES6 features” is probably less useful for libraries (whose authors can constrain themselves), but I’m not sure we should enable loose for apps, especially considering this tool is meant for beginners as well. |
@mmgm No, I would agree as well - it is true that in the majority of cases it won't matter but most users don't know what loose mode provides/does and we don't want users relying on non-spec behavior just to make the output a bit shorter/faster. |
Worth noting that as-is,
|
Woah, this sure is going to be confusing to Redux users (who use |
I think @taion's comment is a bit misleading. If we reach the code path where Array.from is called, then a is not an array and [...a] is guaranteed to be an [a] in loose mode, ie. to not work, but not throw an error. I agree that this is seemingly a bug in Babel (unless it's their strategy to not polyfill functionality but only transform syntax. Is that the case?), but it's certainly not resolved by switching to loose. |
To be specific – the problem there is that if you try to spread a non-array value, If you don't have a polyfill:
This is less an argument for |
@mmgm Yeah you're absolutely right. This is much more of an argument to either polyfill the ES2015 functionality that the helpers need, or for Babel to fix this bug upstream. |
I think that for now, we’ll leave |
@mmgm Right, Babel as a transform won't polyfill anything by itself since it only does syntax. For that we have babel-polyfill or babel-plugin-transform-runtime. http://babeljs.io/docs/usage/caveats/#polyfills |
Is it intentional that Babel transforms syntax into something that requires a polyfill, though? It's unintuitive to me that transpiling |
The specific danger here is that, if I do e.g. |
@taion I dislike The same limitation applies for |
@loganfsmyth Got it. My misunderstanding, thanks. |
I wish there were a good way to just throw there, though. There's nothing enforcing that the correct polyfills get pulled in, and inadvertently ending up with code that works for me but not my users is a really bad feeling. |
Yeah I don't disagree there, Babel doesn't currently do a great job of signaling any of that. |
Also worth noting that, if I understand correctly, generators are transpiled to code that not only requires a polyfill, but requires a specific runtime library to essentially pollute your global scope (unless you use plugin-transform-runtime). I understand your issue with this approach and for what it's worth, I completely agree with you. But this seems like more of Babel-wide problem than an issue with loose mode or regular (strict? Spec?) mode. |
I think it's relatively well-known among Babel users that generators require a runtime. I was very surprised to realize that those other language features required polyfills, though – I'd assumed they hadn't. I opened #269 to note that create-react-app should ship those polyfills; otherwise those transpiled language features will fail for users of applications built with create-react-app that have the misfortune of using old browsers. |
Almost every React package that I'm aware of uses the loose version of the preset to transpile, given that
es2015-loose
produces code that's easier to understand and more performant.As such, it would probably make the most sense to use
es2015-loose
at least for the production Babel config. There are a few edge cases where it allows illegal code to work, so it may not be appropriate for the development config, but I think any "serious" production Babel config should be expected to usees2015-loose
rather thanes2015
.The text was updated successfully, but these errors were encountered: