Jest で「Cannot use import statement outside a module」が解決できない
Jest は既定でテストを CommonJS として実行するため、変換されていない ESM の import を読むと SyntaxError になる。
babel-jest / ts-jest で変換するか、transformIgnorePatterns で ESM 依存を変換対象に含める。
公開:
要約
Jest は既定でテストを CommonJS(CJS)として実行する。
ソースや依存パッケージが素の import / export(ESM)のまま Jest に渡ると、「Cannot use import statement outside a module」が投げられる。
解決の方向は 1 つで、「Jest に変換させる」こと。
自分のコードは babel-jest か ts-jest でトランスパイルし、node_modules 内の ESM 専用パッケージは transformIgnorePatterns の除外を解いて変換対象にする。
よくある原因
- 変換設定が無い:
babel-jestは入っていても preset が無く、importがそのまま残る。 - ESM 専用の依存: 依存パッケージが ESM のみ提供で、既定の
transformIgnorePatterns(node_modulesを除外)が変換しない。 - 本物の ESM で動かしたい:
package.jsonのtype: "module"前提なのに、Node の ESM 実行フラグを付けていない。
解決策
1. 自分のコードを Babel で変換する
babel.config.js に preset を置くと babel-jest が import を CJS へ変換する。
// babel.config.js
module.exports = {
presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
};導入は次の通り。
npm i -D babel-jest @babel/core @babel/preset-env2. ESM 依存だけ変換対象に含める
既定では node_modules は変換されない。
ESM のみの依存だけ除外を解く。
// jest.config.js
module.exports = {
transformIgnorePatterns: ['node_modules/(?!(query-string|other-esm-pkg)/)'],
};3. 変換せず ESM のまま動かす
ネイティブ ESM で実行したい場合は Node を --experimental-vm-modules 付きで起動する(公式の ESM ガイド(新しいタブで開く))。
NODE_OPTIONS=--experimental-vm-modules npx jestこの場合 jest.mock は使えず、jest.unstable_mockModule と動的 import() に置き換える点に注意する。