Fix 'cannot use import statement outside a module'

By

Learn how to fix the cannot use import statement outside a module error by adding type module to package.json in Node.js, or to your script tag in browsers.

~~~

The error Uncaught SyntaxError: cannot use import statement outside a module means you’re using the import keyword in a file that’s not treated as an ES module. In Node.js you fix it by adding "type": "module" to package.json. In the browser you fix it by adding type="module" to the script tag.

I stumbled on this error while importing a function from a JavaScript file.

This error occurs for one reason: you’re trying to use import and you’re not inside an ES module.

It can happen in a Node.js environment, or in the browser.

Why does this happen?

JavaScript has two module systems. Node.js started with CommonJS, where you load code with require(). ES modules, with import and export, arrived later as the standard.

Node.js treats .js files as CommonJS by default. The browser treats a plain <script> as a classic script. In both cases, import is not valid syntax there, so the engine stops with this error.

You have to tell the environment: this file is an ES module.

The fix in Node.js

I had to add a package.json file in the folder of the project and add:

{
  "type": "module"
}

With that field, Node.js treats every .js file in the project as an ES module, and import works.

Alternatively, you can rename the file from .js to .mjs. Node.js always treats .mjs files as ES modules, no package.json change needed. This is handy for a single standalone script.

The fix in the browser

In the browser, you have to add the type attribute with the value module when you load the script, like this:

<script type="module" src="./file.js"></script>

instead of

<script src="./file.js"></script>

A pitfall after the fix

Adding "type": "module" switches the whole project to ES modules. If some file in it still uses CommonJS, you’ll trade this error for a new one:

ReferenceError: require is not defined in ES module scope

Same story with __dirname and __filename, which don’t exist in ES modules.

The fix is to convert those files too: replace each require() with an import, and each module.exports with export. So before flipping the switch on a large existing project, check how much code still relies on require(). For a new project, set "type": "module" from day one and you’ll never see this error.

Tagged: Node.js · All topics
~~~

Related posts about node: