A gentle introduction to ESModules in Node.js

October 8, 2021

At the end of the April Node.js v10 reached "end of life". This means that this version will no longer be maintained and will not be patched with fixes for bugs or known security vulnerabilities. (Check more on Node.js Releases page). This also means that every supported version of Node.js JavaScript runtime supports Node's official EcmaScript modules. This brings some controversy because some people would prefer to stick with CommonJS in the Node ecosystem. Nevertheless, ESModules are now a reality, so let's learn how to use them in a Node.js environment.

First of all, we need a JavaScript we want to run:

add.js
1export function add(a, b) {
2 return a + b
3}

Next, we want to import that JavaScript file to the main index.js file.

index.js
1import { add } from './add.js'
2
3console.log(add(2, 2))

Excellent, now let's run it with node ./index.js or, for simplicity node .

terminal
1node .
2(node:3106) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
3(Use `node --trace-warnings ...` to show where the warning was created)
4/Users/lukaspolak/Documents/esmodules/index.js:1
5import { add } from './add.js'
6^^^^^^
7
8SyntaxError: Cannot use import statement outside a module
9 at wrapSafe (internal/modules/cjs/loader.js:979:16)
10 at Module._compile (internal/modules/cjs/loader.js:1027:27)
11 at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
12 at Module.load (internal/modules/cjs/loader.js:928:32)
13 at Function.Module._load (internal/modules/cjs/loader.js:769:14)
14 at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
15 at internal/main/run_main_module.js:17:47

Using ESModules is an opt-in feature. You can either enable it by renaming file extensions from .js to .mjs, or you can opt-in entire directory by adding "type": "module" to package.json file.

First, let's try to rename files to enable usage of ESModules. Do not forget to rename the import.

add.mjs
1export function add(a, b) {
2 return a + b
3}
index.mjs
1import { add } from './add.mjs'
2
3console.log(add(2, 2))
terminal
1node ./index.mjs
24

Awesome! It is working now. Now let's rename files back to the .js extension, and let's add "type": "module" to package.json file.

package.json
1{
2 "name": "esmodules",
3 "version": "0.0.1",
4 "description": "",
5 "main": "index.js",
6 "type": "module",
7 "scripts": {
8 "test": "echo \"Error: no test specified\" && exit 1"
9 },
10 "keywords": [],
11 "author": "Lukas Polak <lukash.polak@gmail.com> (https://lukaspolak.com/)",
12 "license": "MIT"
13}
terminal
1node ./index.js
24

That's it! It is pretty easy to run ESModules in Node.js. There is a lot more to talk about ESModules, you can read the official Announcing core Node.js support for ECMAScript modules article or dig deep to official documentation.