【実務・中級編】 moduleResolutionの選択肢(node, node16, bundler) – TypeScript実践ガイド

「とりあえず `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そのものか)と握手できているかを確認すること。それが、伝説のアーキテクトへの第一歩だ。

健闘を祈る。また何かあればいつでも聞いてくれ。

コメント

タイトルとURLをコピーしました