Tomorrow’s ES Modules Today!
💡 For a deeper dive check out the Node Module Summit video.
esm – A fast, production ready, zero-dependency ES module loader for Node 6+ that delivers an awesome developer experience to boot!
As with its predecessor, developers can easily enable ES modules in many of their favorite tools by using the “require” options of each:
node -r esm
mocha -r esm
nyc -i esm
webpack -r esm
In addition, package authors can now start new
esm enabled packages using one of the following commands:
npm init esm (npm@6)
yarn create esm
-y flag to answer “yes” to all prompts.
Setting the Stage
Before I dig into
esm, let me set the stage with a bit of backstory.
These experiences have shaped how
esm approaches compatibility and interoperability.
esm was initially released, back in August 2017, Node was 9 months away from shipping ES modules unflagged. Now, 8 months later, Node has pushed back unflagging ES modules another 9-27 months tentatively, a new Node Modules Working Group has been formed (I’m a member), and the Node roadmap that once was isn’t necessarily what will be.
Defaulting to “Nodes rules” now, when those rules haven’t yet been ironed out, doesn’t seem like the right move. Developers should be able to pick up ESM and get coding fast. Ideally, ESM support should fall in line with where the ecosystem is today. With zero configuration
esm should be as CommonJS (CJS) interoperable as possible. The things you ❤️, like application performance monitors, bundlers, code coverage instrumenters, transpilers, and type checkers, should continue to just work.
Node’s ESM plans still have the
.mjs file extension as the default mechanism to signal the module parse goal. However, because Node’s
esm locks down
.mjs disabling all
esm options. This means that today,
.js is your best bet for things to just work.
esm is a bridge from the ESM of today to the ESM of tomorrow. As Node’s path to ESM becomes clear,
esm will allow developers to step into it.
You might think because
esm needs zero buy-in or tie-in to these dependencies while ESM support is being ironed out, enabling faster development and greater ecosystem support for
esm than other approaches. This not only unblocks
esm, but also gives it the freedom to take advantage of native helpers, like
Better than “Just works”
ES module syntax is nice to have, but it’s not critical in Node to get things done. The barrier for adoption has to be incredibly low, with clear benefits, or developers will stick with tried and true CJS. This means
esm has to do more than enable instant and seamless ESM adoption.
esmruns in its own context so it’s more resilient to prototype and polyfill tampering.
- Reduce pain points
esmsmooths over API roughness across Node versions. For example,
require.resolve.pathsenhancements are in Node 8+, but are unavailable in Node 6. With
esmyou get access to these APIs, even in Node 6.
- Improve performance
esmcan improve your application’s startup time by leveraging engine code caches that projects like Parcel, Webpack, Yarn, and many Electron applications benefit from today.
esm is all about removing artificial barriers to, and empowering developers with, modern syntax.
esmdevelopers can write ESM for both server-side and client-side. For example,
esmenhances server-side rendering of Svelte components and allows cross platform applications to be written entirely in ESM.
Quokka.js and Wallaby.js offer scratchpads and integrated testing for text editors, like VS code. Both projects use
esmto enable support for real-time ESM syntax without jumping through additional hoops, using ESM-only loader hooks, juggling mime-types, or forking code bases. For Quokka.js, the integrated scratchpad,
esmeven supports parsing unsaved documents without file extensions!
Pay it forward
esm, I’ve been on the lookout for opportunities to positively impact others. The following are a few examples of this.
- Babylon was patched to enable parsing and linting of top-level
- Node was patched to ensure
--requireoptions work together.
- The work in progress pull request to support named exports of builtin Node modules is based on
esm’s early implementation.
npmES modules proposal, which spurred the creation of the Node Modules Working Group, took
esmas inspiration that alternative implementations were possible.
esm is celebrating its stable release there’s still plenty of things to come.
- The foundation for loader hooks has been laid in
esmso, when things solidify in Node,
esmwill follow suit.
- I’m teaming up with
npm init <create-pkg-name>!
- Experimental WASM support will land soon. Using the
wasmoption you’ll be able unlock loading
.wasmfiles in CJS and ESM!
I’ve seen the delight of developers when their ESM code just works and hope
esm can serve as a reference implementation and powerful example of what is possible!