なぜ今さら `outDir` と `rootDir` なのか? ― プロジェクトの「骨格」を正す話
現場でプロジェクトを引き継いだとき、`tsconfig.json` を開いて「なぜかコンパイル後のJSファイルがソースコードの中に混在していてゴミ屋敷状態になっている」なんて経験はないだろうか。あるいは、`dist` 配下のディレクトリ構造がソースコードと微妙にズレていて、デバッグ時に迷子になったりすることはないだろうか。
TypeScriptの `compilerOptions` は数あれど、プロジェクトの「住所」を決める `outDir` と `rootDir` は、いわば家の基礎工事だ。ここが歪んでいると、後々のビルドパイプラインやCI/CDで必ず痛い目を見る。今日は、中級エンジニアなら絶対に押さえておくべき、この2つの設定の「正解」と、その裏側にある挙動について深掘りしていく。
—
1. `rootDir`: ソースの「聖域」を定義する
`rootDir` は、TypeScriptが「ここから先が俺のコンパイル対象だ」と認識するスタート地点だ。
多くのエンジニアがデフォルト(未設定)のままにしているが、これが落とし穴になる。未設定の場合、TypeScriptは「プロジェクト内のすべてのTSファイルが含まれる最も浅いディレクトリ」をルートと見なす。もし `src` 以外に `tests` や `scripts` が混在していると、コンパイル後のディレクトリ構造が思わぬ階層になり、`import` が壊れる原因になる。
ベストプラクティス:
迷わず明示的に設定せよ。これだけで、プロジェクトの構造が「宣言的」になり、コンパイラの迷いを排除できる。
{
“compilerOptions”: {
// プロジェクトのソースコードは src 以下にしかないことを明示する
“rootDir”: “./src”
}
}
—
2. `outDir`: コンパイル後の「避難所」を作る
`outDir` は、変換されたJavaScriptや型定義(`d.ts`)を吐き出す出力先だ。ここでの鉄則はただ一つ、「ソースコード(src)の外に出すこと」。
これを怠ると、エディタのファイル検索や、Gitの管理対象(`.gitignore`)で地獄を見る。`src` ディレクトリの中に `dist` が生成されるような構成は、コードベースが肥大化したときに、IDEの補完候補が重複して表示されるなど、地味にストレスを蓄積させる。
—
3. 実践:綺麗なプロジェクト構成のサンプル
では、実務でよく使われる「堅牢な構成」を見てみよう。
my-awesome-app/
├── src/ # ソースコードの聖域
│ ├── index.ts
│ └── utils/
│ └── logger.ts
├── dist/ # コンパイル後の戦場(Git管理外)
├── tsconfig.json # 設定ファイル
└── package.json
tsconfig.json の推奨設定:
{
“compilerOptions”: {
“target”: “ESNext”,
“module”: “CommonJS”,
// ソースコードのルートを明確にする
“rootDir”: “./src”,
// コンパイル後のファイルはここに集約する
“outDir”: “./dist”,
// コンパイル後のファイル構造をソースと一致させる(重要!)
“declaration”: true,
“declarationDir”: “./dist/types”,
// 開発体験を向上させるためのオプション
“sourceMap”: true,
“removeComments”: true // 本番用ビルドではコメントを消して軽量化
},
“include”: [“src//”]
}
—
4. 裏側で何が起きているのか?(ブラウザとコンパイラの視点)
TypeScriptはあくまで「トランスパイラ」だ。`rootDir` と `outDir` を設定することで、TypeScriptコンパイラ(`tsc`)は、「`src` 内のディレクトリ構造を、そのまま `dist` に写像(マッピング)する」という処理を行う。
- `src/utils/logger.ts` は、`dist/utils/logger.js` になる。
この「構造の保存」がなぜ重要かといえば、Node.jsのモジュール解決や、将来的にES Modules(ESM)へ移行する際に、相対パスが壊れないようにするためだ。もし `rootDir` を適切に設定していないと、コンパイラが「どこがルートか」を誤認し、出力先の階層が一段深くなったり(例: `dist/src/…`)、予期せぬディレクトリ名が混入することがある。
ブラウザ側から見れば、コンパイル後のJSはただのファイル群に過ぎない。しかし、デバッグ時に生成される `.map` ファイル(sourceMap)は、`rootDir` を基準に「元のTSファイルの場所」を特定している。ここが正しく設定されていないと、ブラウザのデベロッパーツールでソースコードをクリックした際、「ファイルが見つかりません」というエラーに直面することになる。
—
シニアからの最後のアドバイス
「とりあえず動けばいい」という段階を卒業したなら、設定ファイルはプロジェクトの仕様書だと考えるべきだ。
`rootDir` と `outDir` を明示することは、後から参加するメンバーに対して「我々のソースはこのディレクトリにあり、成果物はここに出力される」という明確な境界線を引くことと同義だ。チーム開発において、この「暗黙の了解を減らす」努力こそが、バグを減らし、メンテナンスコストを下げる唯一の道だ。
今日、自分のプロジェクトの `tsconfig.json` を開いてみてほしい。`rootDir` と `outDir` は、整理整頓されているだろうか? もし未設定なら、今すぐ設定して、プロジェクトに「秩序」を取り戻してやってくれ。

コメント