Import ES6 Modules in Node.js

Janne Kemppainen |

With the ECMAScript modules definition we can use the import and export keywords to load and publish library code. However, if you try to use them in your Node.js project you might encounter the following error:

SyntaxError: Cannot use import statement outside a module

This happens because while Node.js fully supports ES module imports and exports it treats your JavaScript code as CommonJS by default. Node expects your packages to be imported with the require function like this:

const axios = require("axios");

but gives an error message because it sees this instead:

import axios from "axios";

The fix is simple, enable ES modules with one of these ways:

  • rename your ES6 modules from the .js extension to .mjs
  • add "type": "module" to your package.json file to load all files under it as ES modules

If you pass the code through STDIN or with the --eval argument as a string parameter you will need to add --input-type=module to your node command. This does not work for code that you run from a file, use one of the two other options instead!

Support for ECMAScript nodules became stable on Node 15. In prior versions the support is labeled experimental so you may see some warnings.

Now you can to use the import keyword without errors! If you need a refresher on the ES6 module syntax there are great examples on the MDN Web Docs.

Can you mix import and require?

In one file you need to stick to one type of import syntax. The ES module syntax supports importing from CommonJS files so you don't necessarily need to make the switch for all files in a large project. If the type definition in the package.json is set to module you can rename the remaining CommonJS formatted files to the .cjs extension.

An alternative way is to create a package.json file inside the directory that contains your CommonJS files and define the type as commonjs. Node will then handle them properly. The type definition can be the only thing in the configuration file, so the following is also a valid package.json:

{ "type": "commonjs" }

If your CommonJS module looks something like this:

// age.cjs
function printAge(age) {
  console.log(`The age is ${age}`);
}

module.exports = { printAge }

Then you can import and use it normally on the ES6 side:

// main.js
import { printAge } from './age.cjs'
...

The opposite is not true, so you cannot require ES6 modules since they are loaded asynchronously. You could use the dynamic import() function which is asynchronous but try to avoid it if at all possible. You can't await code on the top level of CommonJS code which makes the dynamic import a real hassle to use.

For more details check the official Node documentation. It should answer most of your questions, though at times it can be hard to find what you're looking for.

I hope this has answered some at least some of your questions. If you found these instructions unclear or find something that needs to be corrected then add your comment on the embedded tweet!

Discuss on Twitter

Subscribe to my newsletter

What's new with PäksTech? Subscribe to receive occasional emails where I will sum up stuff that has happened at the blog and what may be coming next.

powered by TinyLetter | Privacy Policy