プログラミングTypeScriptを読む進めているのですが、tscコンパイラの出力時の動きに、気になる挙動を発見しました。
ソースディレクトリが1つでコンパイルした時の出力先
tsconfig.jsonは、"outDir": "./dist"
としている状態です。
コンパイルすると、dist/配下にtest.tsが出力されます。
$ tree src src └── test.ts $ npx tsc $ tree dist/ dist/ └── test.js
ソースディレクトリが複数でコンパイルした時の出力先
先ほどの例に、src2を追加して検証します。
$ tree src src └── test.ts $ tree src2 src2 └── test2.ts $ npx tsc $ tree dist/ dist/ ├── src │ └── test.js └── src2 └── test2.js
出力結果を確認すると、test.jsの出力先が変わっていることが分かります。
ソースディレクトリが1つの場合は、test.jsはdist/配下に直接展開されていました。 ところがソースディレクトリを2つに増やした途端、test.jsの出力場所はdist/src/配下に変化しました。
rootDirの未設定が原因である
この挙動さが発生する理由は、tscコンパイラにソースディレクトリのパスを明示していないことが原因でした。
たとえば、tsconfig.jsonで "rootDir": "./"
と明示した状態で、再度コンパイルしてみます。
$ tree src/ src/ └── test.ts $ npx tsc $ tree dist/ dist/ └── src └── test.js
今度はtscコンパイラが起点とするディレクトリを明示しているため、ソースディレクトリが1つであってもdist/src配下に出力されていることがわかります。
まとめ:tsconfig.jsonのrootDirは明示的に指定したほうが良い
予期せぬディレクトリ階層でJSファイルが出力されることを防ぐため、tsconfig.jsonのrootDirは明示するほうが良さそうです。
参考:tsconfig.jsonの各種ディレクトリオプション
Programming Fieldさんの記事が参考になりました。
rootDir を指定しなかった場合は、全ての入力ファイルで共通の親ディレクトリを rootDir として扱い、前述のルールにのっとって出力先を決定します。
- 例: 入力ファイルが「src/main/foo.ts」と「src/main/bar.ts」の2つである場合 → rootDir は「src/main」の扱いとなる
- 例: 入力ファイルが「src/main/foo.ts」と「src/main/bar.ts」と「src/gen/pork.ts」の3つである場合 → rootDir は「src」の扱いとなる
- 例: 入力ファイルが「src/main/foo.ts」と「src/main/bar.ts」と「src/gen/pork.ts」と「externals/banana.ts」の4つである場合 → rootDir は「.」(プロジェクトディレクトリと同じ)の扱いとなる