Tuning Babel to your runtimes
A talk by Christophe Porteneuve at dotJS 2016
A talk by Christophe Porteneuve at dotJS 2016
const christophe = {
age: 39.0848733744011,
family: { wife: 'Élodie', son: 'Maxence' },
city: 'Paris, FR',
company: 'Delicious Insights',
trainings: ['JS Total', 'Node.js', 'Git Total'],
upcoming: ['ES2015+', 'GitHub', 'Performance Web'],
webSince: 1995,
claimsToFame: [
'Prototype.js',
'Ruby On Rails',
'Prototype and Script.aculo.us',
'Paris Web',
'NodeSchool Paris'
]
}
It’s pretty sweet, actually. Take ES0215:
And 90% is usually plenty enough 😉
Native ES2015 modules are still a work in progress.
(Just wait for a later talk today…)
But we want that syntax now! I mean, it’s so awesome:
import React, { PropTypes } from 'react'
export default function Gauge ({ value, max = 100 }) {
return <LinearProgress mode='determinate' value={value} max={max} />
}
And what about older browsers? What about IE? What about older Firefox, Chrome, or just Node 4.x?
We just talked about ES2015, but we’re at ES2016 now, right?
And next year, what do we do with ES2017? And the year after that?
Starting with Babel 6, we can cherry-pick the syntaxes we want to transpile. Everything else is left as-is (deemed native).
The bigger the native support gets, the smaller our transpiled share needs be. There is a strong incentive to avoid the “bulldozer,”, transpile-everything approach we get in most tutorials, generators and starter kits.
We build / watch faster, and eventually run faster (as native catches with, then overcomes, transpiled code performance).
A syntax plugin lets the parser understand a syntax amidst your JS code stream. But Babel doesn’t necessarily transpile it.
A transform plugin instructs Babel to transpile stuff towards ES5. It automatically leverages any syntax plugin it may need.
But there are tons: Babel currently offers 60+ transforms, 21 of which are just about ES2015+!
So we get presets: theme-based groupings of plugins for a specific purpose. These fan out like so…
Of course you can mix and match presets and plugins.
As we’ve seen, Babel already handles ES2016, ES2017, and stages that will feed into later versions. For instance:
And we also have (official!) plugins for third-party syntaxes (most notably JSX and Flow annotations), module conversion (e.g. ES2015 ➡️ CommonJS), minification/optimization (notably for React)…
Most people use a JSON .babelrc file
If you run all your Babel stuff through npm scripts though, you may elect to stuff your Babel config in your package.json (in a "babel"
key).
{
"presets": ["latest-minimal"],
"plugins": [
"transform-object-rest-spread", "transform-class-properties",
"transform-function-bind"
]
}
{
"presets": [["env", {
"targets": { "browsers": "> 1%, last 2 versions" }
}]],
"plugins": [
"transform-object-rest-spread", "transform-class-properties",
"transform-function-bind"
]
}
You need to transpile pretty much everything. IE9 has 100% ES5 (except the strict mode), but 0% ES2015. IE10 has 3%, IE11… 11%. So there.
"presets": ["es2015"]
or
"presets": ["latest"]
Pick the last 2 versions (a la Autoprefixer), trim to 1+% browser share, check out Kangax’s compatibility table, cross-ref everything…
Or just use env:
"presets": [
["env", {
"targets": {
"safari": 10, // SF9 is only 54%…
"browsers": "> 1%, last 2 versions"
},
"debug": true
}]
]
There are specific presets, maintained by the community. But just go with generic feature detection:
"presets": ["latest-minimal"]
or
"presets": [
["env", {
"targets": { "node": "current" },
"debug": true
}]
]
TS ≈ ES2016 + optional type annotations (+ JSX compat)
TS2 transpiles to ES5 by default, but can target ES2015.
Built in VS2013u2 and later + VSCode.
Not much type inference; mostly relies on annotations.
As often with IntelliSense, many external pre-compiled typedefs to avoid deep inference. Enormous repository on DefinitelyTyped.
The documentation lists a number of “classic” integrations: Browserify, Webpack, Grunt, Gulp, JSPM/Rollup, etc.
TL;DR: works pretty well.
TS isn’t the only way to get fine-grained type information on JS code. The Flow project, from Facebook, is excellent.
I often heard that Flow feedback messages were more useful/actionable than TS’, but haven’t really compared them personally.
Do note that Babel can go through Flow-annotated code.
Christophe Porteneuve
Slides are at bit.ly/dotjs-babel-tuning