Node.jsでimportでES moduleのコードが動作しないときの対処法

importを使用したコードが動作しない

Node.jsを使用する際にimportでES moduleをロードするコードが動作しないことがある。

例として以下のようなコードで発生する。

import jsdom from 'jsdom';

const { JSDOM } = jsdom;

const dom = new JSDOM('<html><p>Hello world</p></html>');
const document = dom.window.document;
console.log(document.querySelector("p").textContent);
// "Hello world"
$ node index.js
(node:43574) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use node --trace-warnings ... to show where the warning was created)
import jsdom from 'jsdom';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:1117:16)
at Module._compile (internal/modules/cjs/loader.js:1165:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1221:10)
at Module.load (internal/modules/cjs/loader.js:1050:32)
at Function.Module._load (internal/modules/cjs/loader.js:938:14)
at Function.executeUserEntryPoint as runMain
at internal/main/run_main_module.js:17:47

エラーのWarningに原因が書かれているがES moduleを使用する際は拡張子は.jsではなく.mjsでなければならない。

# 拡張子を.mjsにすると動作する
$ node index.mjs
Hello world

拡張子を.mjsにしても動作しない場合

拡張子を.mjsにしても動作しない場合はNode.jsが最新のバージョンになっていない。

Node.jsのバージョンは「node -v」のコマンドで確認できる。

例えばバージョンが13.2未満の場合は--experimental-modulesが必要になる。

$ node --experimental-modules index.mjs

また、13.2以上でも14以上のバージョンでなければ以下のExperimentalWarningが毎回表示されてしまう。

ExperimentalWarning: The ESM module loader is experimental.

このExperimentalWarningは14以上のバージョンでなければ消えないので、特に理由がなければnodeを最新のv14.xにアップデートしたほうが良いです。