Cloudflare (npm create cloudflare) で作った React + Vite プロジェクトに @ エイリアスを導
この記事は、個人メモを下にGPT-5に作成してもらいました。
簡単に見たい方は、こちら に個人メモをそのまま貼り付けたページを作りましたので、参考程度にご覧ください。
Cloudflare の公式テンプレート (npm create cloudflare@latest -- <app> --framework=react
) で作成した Vite + React プロジェクトには、@
エイリアス(@/components/...
のような書き方)が最初は設定されていません。
そのため自分で設定する必要がありますが、tsconfig.base.json
を分割している構成だと少しハマりやすいポイントがあります。
この記事では設定手順と、なぜ「tsconfigPaths
を入れたのに解決されない」状態になるのかを整理します。
TL;DR (要約)
-
vite-tsconfig-paths
を導入しても動かない場合、プラグインが参照しているtsconfig.json
にpaths
が存在していない可能性が高い -
tsconfig.base.json
を作った場合はtsconfigPaths({ projects: ['tsconfig.base.json'] })
のように対象を明示する - あるいはルートの
tsconfig.json
にもpaths
を複製するか、Vite のresolve.alias
で直接書いてしまう
ゴール
src
配下のファイルを以下のように書けるようにする:
import '@/App.css'
import '@/components/Button'
環境例
- Node: 18+
- パッケージ生成:
npm create cloudflare@latest -- my-react-app --framework=react
- ツール: Vite + React + TypeScript + Cloudflare プラグイン
なぜデフォルトで @ エイリアスがないのか
npm create cloudflare
で生成される React テンプレートは、標準的な Vite テンプレートよりも「Cloudflare 向け設定(Worker / Pages 等)」を優先しており、パスエイリアスは必須機能ではないため初期値に含まれていません。
導入ステップ
1. 依存を追加
npm install -D vite-tsconfig-paths
tsconfig.base.json
を作成
2. プロジェクトルートに配置:
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["./src/*"],
"~/*": ["./public/*"]
}
},
"include": [
"**/*.ts",
"**/*.tsx",
"**/*.css"
]
}
ポイント:
-
baseUrl
は"./"
(プロジェクトルート) - 必要最低限なら
"~/*"
は省略してもよい(public
はルートパス/foo.png
で参照できるため)
tsconfig.app.json
/ tsconfig.node.json
から継承
3. 既存の それぞれに extends
を追加:
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
// 既存の設定 …
}
}
(既存プロパティはそのまま残して OK)
vite.config.ts
にプラグインを追加
4. import {defineConfig} from 'vite';
import react from '@vitejs/plugin-react-swc';
import {cloudflare} from "@cloudflare/vite-plugin";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [
tsconfigPaths({
projects: ['tsconfig.base.json'] // ← ここが重要
}),
react(),
cloudflare(),
],
})
なぜ projects
が必要?
→ デフォルトだとルートの tsconfig.json
(または最初に見つかったもの)を読む。そこに paths
が無いと何も alias 化されない。
5. 動作確認
// 例: src/main.tsx など
import '@/App.css'
npm run dev
を再起動して、解決エラーが消えていれば成功。
よくあるハマりどころ
症状 | 原因 | 対処 |
---|---|---|
直書きの @/App.css が解決されない |
プラグインが base の tsconfig を読んでいない |
projects オプションを指定 |
TypeScript は補完できるのに Vite がビルド失敗 | TS 側はパス解決できるが Vite に alias 未設定 |
tsconfigPaths を plugins に追加していない / 順序が不適切 |
Worker 用ビルドでだけ失敗 | worker 用 tsconfig が base を extends していない |
tsconfig.worker.json も修正 |
CI で突然失敗 | ローカルには古い tsbuildinfo が残っていた |
rm -rf node_modules/.tmp などでキャッシュ削除 |
切り分けの最速手段
一時的に Vite へ直書きしてみる:
resolve: {
alias: { '@': new URL('./src', import.meta.url).pathname }
}
これで動いた → vite-tsconfig-paths
の設定問題
動かない → ファイルパス / 大文字小文字 / 実在確認を再チェック
代替アプローチ (比較)
方法 | メリット | デメリット |
---|---|---|
vite-tsconfig-paths | TS と Vite の同期が簡単 | マルチ tsconfig だと設定追加が必要 |
resolve.alias 手書き | 仕組みが単純で可視性が高い | TS 側にも paths を二重管理したくなる |
何もしない | 相対パスだけで完結 | 階層が深くなると可読性低下 |
個人的には「単一プロジェクト: resolve.alias」「複数ツール共有 or monorepo: tsconfigPaths」が分かれ目になりやすいです。
moduleResolution: "bundler"
について
moduleResolution: "bundler"
を使っている場合、NodeNext 系と微妙に解決挙動が違うことがあります。もし paths
が tsc --showConfig
に出力されないなど意図しない挙動があれば、一時的に "NodeNext"
に戻して差分を観察するのも手です。
確認コマンド:
npx tsc --project tsconfig.app.json --showConfig | grep '"paths"'
ディレクトリ例
project/
tsconfig.json
tsconfig.base.json
tsconfig.app.json
tsconfig.node.json
vite.config.ts
src/
App.tsx
App.css
components/
Button.tsx
App.tsx
:
import '@/App.css'
import '@/components/Button'
運用ポリシー例
- 相対パス推奨: 近接 (同階層 or 2 階層以内)
-
@/
使用: 横断的 (components, lib, hooks, styles, config) - 短縮 alias を増やしすぎない (
@c
,@u
などは後から読む人に不親切)
トラブルシューティング チェックリスト
# 1. プラグインは入っているか
grep -n "tsconfigPaths" vite.config.ts
# 2. 参照対象は正しいか
cat tsconfig.base.json | grep '"paths"'
# 3. tsc が alias を認識しているか
npx tsc --project tsconfig.app.json --showConfig | grep '"@/*"'
# 4. Vite の再起動をしたか(ホットリロードでは拾わないことあり)
まとめ
-
tsconfig.base.json
を切っているとvite-tsconfig-paths
は “読んでいない tsconfig” 問題にハマりやすい -
projects
オプションで明示するか、ルートに paths を複製する - 切り分けは
resolve.alias
の直書きが最速 - 過剰な alias 追加はメンテ負荷になるので最小限から始める
付録: もっとシンプルにしたい場合
小規模なら分割をやめてルート tsconfig.json
を 1 枚にまとめ、tsconfig.app.json
などを削減することで混乱を避けやすくなります。
何か別の周辺(Cloudflare Workers 側の import、Vitest 設定など)も気になればコメントください。改善案も歓迎です。お疲れさまでした。
Discussion