I’m happy to provide actual data (and I’m sorry I didn’t have it ready during my talk), but first I want to clear up some confusions that I see emerging in this thread.
Optionality
Both packages (ecmascript
and es5-shim
) will be removable, for those who do not wish to enable the new features, or who do not care about supporting older browsers. This was always a design constraint for the ES2015 project, precisely so that no one could complain we made their app slower or larger without giving them the opportunity to opt out. I do not mean to suggest we actually think the new features are too slow or too bloated for production use. In fact, if you let those unmeasured concerns keep you from using the new ecmascript
package, you’ll just be cheating yourself out of a better development experience.
Caching
All compilation is cached, so the cost of incremental reloads is never more than the cost of compiling the files that changed, and only those files. If recompilation ever takes longer than switching from your text editor to your browser, something has gone terribly wrong, and you should file a GitHub issue (with a reproduction, if possible).
If you are writing a package that uses ecmascript
but also contains large files that should not be compiled, you can selectively disable compilation when you call api.addFiles
by passing the {transpile:false}
option, e.g.
api.addFiles("backbone.js", "client", { transpile: false });
Runtime footprint
Here is the entire runtime library that the ecmascript
package uses. It contains only the helper functions we need, so it’s smaller than Babel’s own library of external helpers. The benefit of using a runtime library is that we don’t have to keep injecting the same helper functions at the top of every compiled file, which is what Babel does by default.
Generated code size
As part of our due diligence in deciding which language features to enable, we examined the output of every candidate transformation.
In some cases we decided not to enable the transformation, either because its runtime was large, or because the generated code was verbose. Generator functions are a good example of both problems, and I should know, because I am the author of Regenerator. That said, if you have a good use case for generator functions in Meteor code, let us know, and we will consider enabling them.
In other cases we tweaked the Babel options so that the generated code would be smaller or faster. For example, we compile for
-of
loops in “loose” mode, so that code like this
for (let x of foo()) {
console.log(x);
}
gets translated to this instead of this.
In other words, if you refer to that performance comparison table that @vjau mentioned above, make sure you look at the babel-loose rows instead of the babel rows. For example, for
-of
loops over arrays are much faster in loose mode.
Pay for what you use
Perhaps most importantly, any code that avoids using ES2015 features will have exactly the same generated code size and performance characteristics as ordinary ES5 code, because the compiler will just leave it untouched.
Since truly performance critical code tends to be isolated in relatively few hot spots, you always have the option of rewriting just those few bits of code in whatever style performs best, and otherwise reaping the benefits of the new language features throughout the overwhelming majority of your code.
When native support eventually catches up, your code will be ready to take full advantage of the native performance boost—but only if you’ve already been using the new language features via compilation!
Avoid relying on microbenchmarks
When and where performance optimization will be necessary is highly dependent on the details of your specific application. I’m reluctant to talk about performance without referring to real-world examples, because microbenchmarks are misleading. Without actually looking at someone’s code, it’s difficult to give any meaningful advice about performance optimization, and so I would strongly discourage anyone from presuming to give that kind of unspecific advice in this forum.
Let’s have some numbers!
Using the latest devel
branch version of Meteor, I created a new app, then built it for production with all four combinations of enabling/disabling the ecmascript
and es5-shim
packages.
Listed below are the resulting sizes of the bundle/programs/web.browser/<hash>.js
file (which is the file that gets sent to the browser):
Without ecmascript
, without es5-shim
: 327.80KB (+0KB, 1x)
With ecmascript
, without es5-shim
: 335.95KB (+8.15KB, 1.025x)
Without ecmascript
, with es5-shim
: 342.40KB (+14.60KB, 1.045x)
With ecmascript
, with es5-shim
: 350.55KB (+22.75KB, 1.069x)
If you use gzip (and you do, unless you use meteor run
for production, in which case you have bigger problems!), the difference between the largest and smallest versions is only 7.66KB (or just 2.63KB with ecmascript
only). Is that enough to cause concern? We can’t make that call for you, but now you have enough information to decide for yourself.