1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Vite + Jest】CommonJSとESMの違いを理解してテスト環境のエラーを解消する

1
Posted at

はじめに

Vite + React + TypeScriptのプロジェクトでJestを導入したとき、こんなエラーに遭遇しませんでしたか?

  • The 'import.meta' meta-property is only allowed when the '--module' option is...
  • ECMAScript imports and exports cannot be written in a CommonJS file under 'verbatimModuleSyntax'

これらのエラーの根本原因は、Vite(ESM)とJest(CommonJS)のモジュールシステムの違いにあります。この記事では、CommonJSとESMの違いを整理し、なぜエラーが起きるのか・どう解決するのかを解説します。

そもそもモジュールシステムとは?

JavaScriptにおける「ファイルの読み込み方式」のことです。主に2つの方式があります。

CommonJS(CJS)

Node.jsで昔から使われてきた方式です。

// エクスポート
module.exports = { hello: "world" };

// インポート
const { hello } = require("./module");

  • Node.jsの標準として長年使われてきた
  • 同期的に読み込む(上から順にファイルを読む)
  • ブラウザでは直接使えない
  • Jestはデフォルトでこの方式で動く

ESNext(ESM / ES Modules)

JavaScriptの公式仕様として策定された方式です。

// エクスポート
export const hello = "world";

// インポート
import { hello } from "./module.js";

  • ブラウザがネイティブで対応している
  • 非同期的に読み込める(パフォーマンスが良い)
  • Viteはこの方式を使っている
  • import.meta.env はESMの機能

なぜVite + Jestでエラーが起きるのか

Vite(アプリ本体)はESNextで動き、Jest(テスト)はCommonJSで動きます。

アプリ本体(Vite) テスト(Jest)
モジュール方式 ESNext(ESM) CommonJS
import文 import / export require / module.exports
import.meta.env 使える 使えない

この違いがあるため、以下のようなエラーが発生します。

エラー①:import.meta が使えない

import.meta.env.VITE_SUPABASE_URL のような記述は、ESMの機能です。CommonJSで動くJestの環境には存在しないため、エラーになります。

エラー②:verbatimModuleSyntax との衝突

tsconfig の verbatimModuleSyntax: true は「ESMの書き方を厳密にチェックする」設定ですが、Jest(CommonJS)で実行されると矛盾が生じてエラーになります。

解決方法:Jest用のtsconfigを分ける

アプリ本体とテストで異なるモジュール方式を使うため、tsconfig自体を分けるのが一番きれいな方法です。

1. tsconfig.jest.json をプロジェクトルートに作成

tsconfig.app.json を継承しつつ、Jest用にモジュール設定を上書きします。

tsconfig.jest.json
{
  "extends": "./tsconfig.app.json",
  "compilerOptions": {
    "verbatimModuleSyntax": false
  }
}

2. jest.config.js で tsconfig.jest.json を指定

jest.config.js
export default {
  preset: "ts-jest",
  testEnvironment: "jsdom",
  setupFilesAfterSetup: ["./jest.setup.ts"],
  transform: {
    "^.+\\.(ts|tsx)$": ["ts-jest", {
      tsconfig: "tsconfig.jest.json", //ここに追加
    }],
  },
  moduleNameMapper: {
    "\\.(css|less)$": "identity-obj-proxy",
  },
};

import.meta.env の対応は下記の記事を参考にしました。
https://qiita.com/shunii/items/b00d556f3730e6b88708

まとめ

  • CommonJS → Node.jsの昔からの方式。require / module.exports。Jestはこっち
  • ESNext(ESM) → JavaScriptの公式方式。import / export。Viteはこっち
  • この2つの世界が混ざるとエラーになりやすい
  • Jest用に tsconfig.jest.json を分けて対応するのが一般的なパターン

Vite + Jestの環境構築でハマったとき、「モジュールシステムの違い」を意識するとエラーの原因が見えてくるはずです。

1
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?