The Future Isn't Now

Have you been paying attention to the recent developments regarding ES modules (ESM) in Node.js? If not, you really should. Earlier this month, support for ESM landed in Chrome Canary, and it stirred up a lot anxiety on Twitter around the actual details of how ESM will be implemented. The Webpack team put out a nice, informative blog post that’s definitely worth a read.

The crux of the issue is that ESM will behave differently than CJS modules, but existing transpilers (like Babel) and packaging tools (like Webpack) that support the ESM syntax have been producing code that behaves a bit like a combination of the two module systems. Code that was written with ESM syntax today will almost certainly need to be refactored within the next year or two. There’s the fear that this could become a sort of “Python 3” moment for the JavaScript community: an awkward, painful transition period as library authors port over their code to the new system.

I think this is one of those obnoxious “teachable moments” about the trade-offs you make when you try to emulate or adopt bleeding edge web standards before there’s an official implementation. It turns out that implementation details are really important, especially when you’re working in an environment where there are multiple, often conflicting implementations that you need to deal with all at once. When Babel first came out, it was often evangelized as a way to write future JavaScript today; the idea was that when ES2015 finally hit browsers and Node.js, you’d be able to just drop the transpiler from your build process and call it a day. The reality is much messier.

Lest you think I’m picking on Babel (a project I genuinely like and use every day) or even JavaScript as a whole, I’d like to point out that this is something that’s happened over and over again in the world of frontend web development. When HTML5 support was trickling out to browsers, the “best practices” were in an almost constant state of churn (RIP <hgroup> and pubdate), and to this very day, the HTML5 document outline is not implemented in any major browser. Another good example is flexbox: the original syntax from 2009 is significantly different than the syntax we use today, but by the time the new syntax came around there were already a slew of JavaScript polyfills for the older syntax. The transition between the old and new flexbox syntax was pretty awkward as I recall.

My point is this: I’m all for taking advantage of new language features, new APIs, and so on, but if you want to stay on the bleeding edge, you’ve got to commit to staying on the bleeding edge. Your code is almost certainly going to need to be refactored at some point. You’re probably going to have to learn a lot of new concepts along the way and, just as importantly, unlearn a lot of stuff you used to know. You should dispense with any illusions that you’re writing future code today, because you don’t actually know what future code will look like. The future isn’t now, it’s later.