できない.dev

Vite で path alias(@/)が解決できない

vite.config.ts で resolve.alias を設定しても @/components/... が解決できない場合、Vite 側の alias と TypeScript の paths の両方を揃える必要がある。

公開: 更新:

実行例あり(2026-09-07 に実環境で検証)

要約

Vite の path alias は Vite (resolve.alias) と TypeScript (tsconfig.paths) の 2 箇所に独立した設定が必要。
片方だけだと「ビルドは通るが型エラー」または「型は通るが実行時に解決失敗」のどちらかになる。

実行例

alias を設定していない状態では、Rollup が @/lib/greet.js を解決できずビルドが終了コード 1 で止まる。resolve.alias を足すとそのままビルドが通り、出力を実行するとエイリアス越しに読み込んだ関数が動いていることまで確認できる。

$ npx vite build
vite v6.4.3 building for production...
transforming...
✓ 1 modules transformed.
✗ Build failed in 16ms
error during build:
[vite]: Rollup failed to resolve import "@/lib/greet.js" from "/tmp/tmp.eKQHw7qXUT/src/main.js".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
    at viteLog (file:///tmp/tmp.eKQHw7qXUT/node_modules/vite/dist/node/chunks/dep-Dm0c1Wj2.js:46504:15)
    at onRollupLog (file:///tmp/tmp.eKQHw7qXUT/node_modules/vite/dist/node/chunks/dep-Dm0c1Wj2.js:46554:5)
    at onLog (file:///tmp/tmp.eKQHw7qXUT/node_modules/vite/dist/node/chunks/dep-Dm0c1Wj2.js:46202:7)
    at file:///tmp/tmp.eKQHw7qXUT/node_modules/rollup/dist/es/shared/node-entry.js:21274:32
    at Object.logger [as onLog] (file:///tmp/tmp.eKQHw7qXUT/node_modules/rollup/dist/es/shared/node-entry.js:23259:9)
    at ModuleLoader.handleInvalidResolvedId (file:///tmp/tmp.eKQHw7qXUT/node_modules/rollup/dist/es/shared/node-entry.js:22004:26)
    at file:///tmp/tmp.eKQHw7qXUT/node_modules/rollup/dist/es/shared/node-entry.js:21962:26
$ echo $?
1
$ npx vite build
vite v6.4.3 building for production...
transforming...
✓ 2 modules transformed.
rendering chunks...
computing gzip size...
dist/main.js  0.07 kB │ gzip: 0.08 kB
✓ built in 40ms
$ echo $?
0
$ node dist/main.js
hello from @/lib/greet.js
$ node check-alias.mjs
resolve.alias: [ { find: '@', replacement: '/tmp/tmp.eKQHw7qXUT/src' } ]

— 2026-09-07 時点の出力

検証環境

検証日
実行環境
node:20Debian GNU/Linux 12 (bookworm)
バージョン
  • Node.js 20.20.2
  • npm 10.8.2
  • Python 3.11.2
  • Git 2.39.5

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  1. vite.config.ts の resolve.alias 未設定、または書式ミス。
  2. tsconfig.json の paths 未設定で TypeScript が解決できない。
  3. 設定ファイルの外にある ESM コードで __dirname を使い、その ReferenceError を alias の解決失敗と混同している(vite.config.* は Vite がバンドルしてから評価するため、"type": "module" でも __dirname は使える)。
  4. Vitest を併用しているが Vitest 側の alias が抜けている。
  5. ESLint の import/no-unresolved が alias を知らない。

解決策

1. vite.config.ts に alias を追加

// __dirname は "type": "module" の有無にかかわらず使える
import { defineConfig } from "vite";
import path from "node:path";
 
export default defineConfig({
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
});
// import.meta.url から組み立てても結果は同じ
import { defineConfig } from "vite";
import { fileURLToPath, URL } from "node:url";
 
export default defineConfig({
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
    },
  },
});

2. tsconfig.json に paths を追加

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

設定後は VS Code の TypeScript Server を再起動する(Cmd+Shift+P → TypeScript: Restart TS Server)。

3. Vitest を使うなら同じ alias を vitest.config.ts に書く

mergeConfig で vite.config.ts を取り込めば二重管理を避けられる。

4. ESLint の resolver を入れる

npm install -D eslint-import-resolver-typescript

.eslintrc に settings: { 'import/resolver': { typescript: true } } を追加する。
詳細は Vite の Shared Options ドキュメント(新しいタブで開く) を参照。

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