できない.dev

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 の除外を解いて変換対象にする。

よくある原因

  1. 変換設定が無い: babel-jest は入っていても preset が無く、import がそのまま残る。
  2. ESM 専用の依存: 依存パッケージが ESM のみ提供で、既定の transformIgnorePatternsnode_modules を除外)が変換しない。
  3. 本物の ESM で動かしたい: package.jsontype: "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-env

2. 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() に置き換える点に注意する。

この記事は役立ちましたか?