できない.dev

Vitest で「Cannot find module」とパスエイリアス(@/)が解決できない

tsconfig の paths は型解決用で、Vitest(Vite)の実行時には効かない。
テストで @/ が Cannot find module になるのは resolve.alias 未設定が主因。
alias を定義するか vite-tsconfig-paths を入れる。

#vitest#alias#vite#tsconfig-paths#resolve

公開:

要約

テストで Error: Cannot find module '@/foo' のように出るのは、@/ のようなパスエイリアスが Vitest の実行時に解決できていないため。tsconfig.jsonpaths はあくまで TypeScript の型解決・エディタ補完用で、実際にモジュールを束ねる Vite/Vitest は resolve.alias を見る(alias | Vitest)。
二つは別物なので、tsconfig だけ書いても実行時には効かない。
alias を Vite 側にも定義するか、tsconfig の paths を同期するプラグインを入れる。

よくある原因

  1. 設定の二重管理漏れ: tsconfig の paths は書いたが、resolve.alias を書いていない。
  2. 相対パス: alias の値を相対パスで書いており、基準ディレクトリがずれて解決できない。
  3. 設定ファイル分離: vite.configvitest.config が別で、テスト側に alias が渡っていない。
  4. require には効かない: alias は import 文のみ対象で、require() は解決しない。

解決策

1. resolve.alias を絶対パスで定義する

vitest.config.ts(または vite.config.ts)のトップレベルに置く(Shared Options | Vite)。

import { defineConfig } from "vitest/config";
import { fileURLToPath } from "node:url";
 
export default defineConfig({
  resolve: {
    alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) },
  },
});

2. tsconfig の paths を同期する

エイリアスを tsconfig 一本で管理したいなら、プラグインで Vite 側へ反映する。

import tsconfigPaths from "vite-tsconfig-paths";
 
export default defineConfig({ plugins: [tsconfigPaths()] });

3. include を確認する

tsconfig.jsoninclude にテストフォルダが含まれているかも確認する。
含まれないと型解決とテスト解決の食い違いが起きやすい。

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