Starting with version 8.5.0 (released in Sep 2017), Node.js supports ES modules natively, if you pass the --experimental-modules
flag and use the .mjs extension for all the files involved. This means we no longer need a transpiler like Babel!
lib.mjs
export const hello = 'Hello world!';
index.mjs
import { hello } from './lib';
console.log(hello);
Run as:
node --experimental-modules index.mjs
That's it! You've written an ECMAScript module and used it, without Babel or any transpilers.
How to publish native ES modules
To publish an ES module to NPM so that it can be imported directly, without Babel, simply point the main field in your package.json
to the .mjs
file, but omit the extension:
{
"name": "mjs-example",
"main": "index"
}
That’s the only change. By omitting the extension, Node will look first for an mjs file if run with --experimental-modules
. Otherwise it will fall back to the .js file, so your existing transpilation process to support older Node versions will work as before — just make sure to point Babel to the .mjs file(s).
Here’s the source for a native ES module with backwards compatibility for Node < 8.5.0 that I published to NPM. You can use it right now, without Babel or anything else.
Install the module:
yarn add local-iso-dt
# or, npm install local-iso-dt
Create a test file test.mjs
:
import { localISOdt } from 'local-iso-dt';
console.log(localISOdt(), 'Starting job...');
Run node (v8.5.0+) with the --experimental-modules flag:
node --experimental-modules test.mjs
Conclusion
It’s very easy to add native ES module support to your Node.js packages. Just rename your ES6+ files to .mjs and update the main entry in package.json
, omitting the extension. This way your modules can be used directly in Node v8.5.0+ with the --experimental-modules
flag.
While support is experimental right now (Feb 2018), it’s unlikely to change significantly and Node plans to drop the flag requirement with v10.
Keep your transpilation script for backwards compatibility and feel free to fork my example native ES module repo.
Further reading
- Using ES modules natively in Node.js
- Setting up multi-platform npm packages
- StackOverflow question (credits to Alexander O’Mara)
Top comments (2)
That's like the one thing I never used babel for.
That's (?:Webpack|Rollup|Parcel)'s job.
As of node v12 the information in this article is no longer correct; please see the announcement from node.