All posts
Engineering··2 min read

Babel, ES6 and the years we all had a build step

A look back at 2016, when transpiling stopped being exotic and every project grew a build — and at what we gained and lost by it.

Numan HussainNuman HussainEntrepreneur · Developer · Team Lead
Babel, ES6 and the years we all had a build step

A look back, written in 2026. ES6 landed in the language in 2015; Babel is what let us use it before the browsers were ready, and that gap defined how JavaScript projects were built for a decade.

The deal we made

Write modern JavaScript, ship something older. Arrow functions, classes, modules, destructuring — all of it, years before Internet Explorer stopped mattering to a client's traffic.

In return, every project acquired a build step. A config file, a plugin list, a preset, and eventually a second config for the tests because they ran somewhere else. It was worth it. But the cost was not the CPU time; it was that the code running in the browser was no longer the code you wrote.

The first time a client's bug only reproduced in the built output, not in development, I lost a day to it. Every transpiled project carries that risk and most teams never budget for it.

What was genuinely better

Modules, above everything. Before them we had script tags in a careful order, or a module loader, or a convention where everything hung off one global object and you prayed. Modules made it possible to say what a file needs, and for a tool to work out the rest.

That single change is what made the tooling of the last decade possible: bundling, tree shaking, code splitting, dependency analysis. None of it works without a statement of what depends on what.

What we over-bought

Polyfills for browsers nobody in the audience used. I built sites in 2016 that shipped a hundred kilobytes of compatibility code for a browser share that a look at the analytics would have shown was a rounding error. Nobody looked, because the preset was the default and defaults are invisible.

Configuration for its own sake, too. Whole afternoons tuning a bundler for a site that would have loaded faster as two script tags.

Where it landed

Browsers caught up. Modules ship natively, async and await are ordinary, and the compatibility argument is largely over. What survived is the tooling built on modules, and a preference for one build that produces one predictable output.

The lesson I carry from it is about defaults: a default you have not examined is a decision someone else made about your project. Once a year, look at what your build is actually emitting and who it is for. Usually a chunk of it is for nobody.

Keep reading