「とりあえず `node` にしておけば動くし、よくわからんからそのままにしている」。もし君が今のプロジェクトでそんな状態なら、一度立ち止まってここを読んでほしい。
TypeScriptの `moduleResolution` は、単なる設定の一項目じゃない。これは君が書いたコードが、ビルドツールやランタイムの世界で「どう迷子にならずに目的のファイルへ辿り着くか」という、インフラの地図そのものなんだ。
今日は、混沌とする現代のフロントエンド開発において、なぜ今 `bundler` が正義なのか、そして `node16` と何が違うのか。現場のリアルな視点で深掘りしていくぞ。
—
1. なぜ `moduleResolution` がこれほど重要なのか?
まず前提を揃えよう。`moduleResolution` は、TSコンパイラ(`tsc`)に対して「import文で指定されたパスを、どうやって実際のファイルパスに変換するか」というルールを教える設定だ。
- `node`: 古のCommonJS時代からの遺産。`node_modules` を再帰的に探すアルゴリズム。
- `node16` / `nodenext`: ESM(ECMAScript Modules)とCJSの混在を厳格にサポートする、Node.jsの現代的な仕様。
- `bundler`: ViteやWebpackなどの「バンドラー」が、Node.jsの仕様を無視して独自に拡張した解決ルール。
昔は「とりあえず `node`」で良かった。しかし、現代のフロントエンドはブラウザ上で動く「バンドラー」の世界。Node.jsのランタイム仕様と、Viteのようなツールが裏で行っている「魔法のような解決」の間には、埋められない溝があるんだ。
—
2. 実務現場でなぜ `bundler` が推奨されるのか
結論から言うと、ViteやNext.jsなどの最新フレームワークを使っているなら、迷わず `moduleResolution: “bundler”` を選ぶべきだ。
理由はシンプル。「Node.jsはブラウザではないから」 だ。
Node.jsの `node16` 設定は、ファイル拡張子(`.js` や `.mjs`)や `package.json` の `exports` を非常に厳格に見る。しかし、バンドラーはもっと柔軟だ。「拡張子なしでimportしても、Viteがよしなに解決してくれる」という開発体験(DX)を重視している。
もしここで `node16` を選ぶと、TSは「そのパスはNode.jsのルール違反だぞ!」と警告を出し、IDE上で真っ赤なエラーが表示される。だが、ビルドしてみると普通に動く。「IDEはエラーなのに、動く」という最悪の技術的負債がここで生まれるわけだ。
—
3. 実践:最強の `tsconfig.json` 設定例
現代的なフロントエンド環境(Vite + TypeScript)での、最も健全な構成を載せておく。これをそのまま自分のプロジェクトに貼り付けてみてくれ。
{
“compilerOptions”: {
// 現代的なモジュール解決。バンドラーの挙動にTSを追従させる
“moduleResolution”: “bundler”,
// ESMをベースにする
“module”: “ESNext”,
// TSの解釈を最新に保つ
“target”: “ESNext”,
// 必須級の最適化設定
“esModuleInterop”: true,
“skipLibCheck”: true,
“isolatedModules”: true,
// パスエイリアスを活用するための設定
“baseUrl”: “.”,
“paths”: {
“@/”: [“src/”]
}
}
}
なぜこの設定が「賢い」のか?
- `moduleResolution: “bundler”`: バンドラーが裏でやっているパス解決のルールをTSに共有する。これにより「動くのにエディタがエラーを吐く」というストレスから解放される。
- `esModuleInterop: true`: `import React from ‘react’` のような、デフォルトエクスポートを持たないライブラリをCommonJSから読み込む際の悪夢(`import as React` と書かなきゃいけない現象)を解消してくれる。これはもう必須の教養だ。
- `isolatedModules: true`: これを有効にすると、`const enum` のような「他のファイルの情報がないとコンパイルできない機能」を禁止できる。Viteなどの高速ビルド環境において、ビルド時間を劇的に安定させる魔法のスイッチだ。
—
4. 最後に:エンジニアとしての心構え
「設定をコピペして終わり」にするのは、ジュニアまでの仕事だ。
もし君が大規模なアプリを運用しているなら、`moduleResolution` を変更した瞬間に、依存関係の解決エラーが数件出るかもしれない。それはバグじゃない。「これまで曖昧だった依存関係が、ようやく可視化された」 という収穫だ。
Node.jsの仕様とブラウザの挙動の差を理解し、バンドラーがどうやってその架け橋を作っているか。そこに思いを馳せられるようになると、君はもう一段上のフロントエンドエンジニアになれる。
何かトラブルが起きたら、まずは `tsconfig.json` の設定が、今動いているツールチェーン(Viteか、Webpackか、あるいはNode.jsそのものか)と握手できているかを確認すること。それが、伝説のアーキテクトへの第一歩だ。
健闘を祈る。また何かあればいつでも聞いてくれ。

コメント