DEV Community

Dan Dascalescu
Dan Dascalescu

Posted on

You probably don't need Babel

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!';
Enter fullscreen mode Exit fullscreen mode

index.mjs

import { hello } from './lib';
console.log(hello);
Enter fullscreen mode Exit fullscreen mode

Run as:

node --experimental-modules index.mjs
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Create a test file test.mjs:

import { localISOdt } from 'local-iso-dt';
console.log(localISOdt(), 'Starting job...');
Enter fullscreen mode Exit fullscreen mode

Run node (v8.5.0+) with the --experimental-modules flag:

node --experimental-modules test.mjs
Enter fullscreen mode Exit fullscreen mode




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

Top comments (2)

Collapse
 
qm3ster profile image
Mihail Malo

That's like the one thing I never used babel for.
That's (?:Webpack|Rollup|Parcel)'s job.

Collapse
 
mikemarcacci profile image
Mike Marcacci

As of node v12 the information in this article is no longer correct; please see the announcement from node.