プロジェクト参照は、TypeScript 3.0の新機能で、TypeScriptプログラムをより小さな部分に構造化できます。
これにより、ビルド時間を大幅に改善し、コンポーネント間の論理的な分離を強制し、コードを新しくより良い方法で整理できます。
また、より高速なTypeScriptビルドを可能にするために、プロジェクト参照と連携するtscの新しいモードである--buildフラグも導入しています。
プロジェクトの例
ごく普通のプログラムを見て、プロジェクト参照がどのように整理に役立つかを見てみましょう。 converterとunitsの2つのモジュールと、それぞれのテストファイルがあるプロジェクトを想像してください。
/ ├── src/ │ ├── converter.ts │ └── units.ts ├── test/ │ ├── converter-tests.ts │ └── units-tests.ts └── tsconfig.json
テストファイルは実装ファイルをインポートしてテストを行います。
ts// converter-tests.tsimport * as converter from "../src/converter";assert.areEqual(converter.celsiusToFahrenheit(0), 32);
以前は、単一のtsconfigファイルを使用した場合、この構造は扱いにくいものでした。
- 実装ファイルがテストファイルをインポートすることが可能でした。
srcが出力フォルダ名に表示されずに、testとsrcを同時にビルドすることはできませんでした。これはおそらく望ましくないでしょう。- 実装ファイルの内部のみを変更すると、たとえ新しいエラーが発生しなくても、テストを再度型チェックする必要がありました。
- テストのみを変更すると、何も変更がなくても実装を再度型チェックする必要がありました。
複数のtsconfigファイルを使用してこれらの問題の一部を解決することはできましたが、新しい問題が発生しました。
- 組み込みの最新チェックがないため、常に
tscを2回実行することになります。 tscを2回呼び出すと、起動時間のオーバーヘッドが増加します。tsc -wは複数の設定ファイルを同時に実行できません。
プロジェクト参照は、これらのすべての問題などを解決できます。
プロジェクト参照とは?
tsconfig.jsonファイルには、新しいトップレベルプロパティreferencesがあります。 これは、参照するプロジェクトを指定するオブジェクトの配列です。
js{"compilerOptions": {// The usual},"references": [{ "path": "../src" }]}
各参照のpathプロパティは、tsconfig.jsonファイルを含むディレクトリ、または設定ファイル自体(任意の名前を付けることができます)を指すことができます。
プロジェクトを参照すると、新しいことが起こります。
- 参照されたプロジェクトからモジュールをインポートすると、代わりにその出力宣言ファイル(
.d.ts)がロードされます。 - 参照されたプロジェクトが
outFileを生成する場合、出力ファイル.d.tsファイルの宣言はこのプロジェクトで表示されます。 - ビルドモード(下記参照)では、必要に応じて参照プロジェクトが自動的にビルドされます。
複数のプロジェクトに分割することで、型チェックとコンパイルの速度を大幅に向上させ、エディタ使用時のメモリ使用量を削減し、プログラムの論理的なグループ化の強制を改善できます。
composite
参照されるプロジェクトでは、新しいcomposite設定を有効にする必要があります。この設定は、TypeScriptが参照プロジェクトの出力をどこで探せばよいかを迅速に判断するために必要です。compositeフラグを有効にすると、いくつかの点が変更されます。
rootDir設定は、明示的に設定されていない場合、デフォルトでtsconfigファイルを含むディレクトリになります。- すべての実装ファイルは、
includeパターンと一致するか、files配列にリストされている必要があります。この制約に違反すると、tscはどのファイルが指定されていないかを通知します。 declarationをオンにする必要があります。
declarationMap
また、declaration source mapsのサポートも追加しました。declarationMapを有効にすると、サポートされているエディターで「定義へ移動」や「名前の変更」などのエディター機能を使用して、プロジェクト境界を越えてコードを透過的にナビゲートおよび編集できます。
outFile付きのprepend
また、参照内のprependオプションを使用して、依存関係の出力を先頭に追加することもできます。
js"references": [{ "path": "../utils", "prepend": true }]
プロジェクトを先頭に追加すると、現在のプロジェクトの出力の上にプロジェクトの出力が含まれます。すべての出力ファイル(.js、.d.ts、.js.map、.d.ts.map)は正しく出力されます。
tscはこの処理を行うためにディスク上の既存のファイルのみを使用するため、一部のプロジェクトの出力が結果のファイルに複数回存在するため、正しい出力ファイルを生成できないプロジェクトを作成することが可能です。例えば、
txtA ^ ^ / \ B C ^ ^ \ / D
この状況では、各参照で先頭に追加しないことが重要です。なぜなら、Dの出力にAのコピーが2つできるため、予期しない結果につながる可能性があります。
プロジェクト参照に関する注意点
プロジェクト参照には、注意すべきいくつかのトレードオフがあります。
依存プロジェクトは、依存関係から構築された.d.tsファイルを使用するため、特定のビルド出力をチェックインするか、エラーが表示されずにエディターでプロジェクトをナビゲートする前に、クローン後にプロジェクトをビルドする必要があります。
VS Code(TS 3.7以降)を使用する場合、バックグラウンドでインメモリの.d.ts生成プロセスがあり、これを軽減できるはずですが、パフォーマンスへの影響があります。非常に大規模な複合プロジェクトの場合は、disableSourceOfProjectReferenceRedirect オプションを使用してこれを無効にすることができます。
さらに、既存のビルドワークフローとの互換性を維持するために、tscは--buildスイッチを指定して呼び出されない限り、依存関係を自動的にビルドしません。--buildについて詳しく学びましょう。
TypeScriptのビルドモード
待望されていた機能は、TypeScriptプロジェクトのスマートなインクリメンタルビルドです。3.0では、tscで--buildフラグを使用できます。これは実質的に、単純なコンパイラーというよりもビルドオーケストレーターとして動作するtscの新しいエントリポイントです。
tsc --build(略してtsc -b)を実行すると、次の処理が行われます。
- 参照されているすべてのプロジェクトを検索します
- それらが最新かどうかを検出します
- 最新でないプロジェクトを正しい順序でビルドします
tsc -bには、複数の構成ファイルパスを指定できます(例:tsc -b src test)。tsc -pと同様に、構成ファイルの名前がtsconfig.jsonの場合、構成ファイル名自体を指定する必要はありません。
tsc -bコマンドライン
任意の数の構成ファイルを指定できます
shell> tsc -b # Use the tsconfig.json in the current directory> tsc -b src # Use src/tsconfig.json> tsc -b foo/prd.tsconfig.json bar # Use foo/prd.tsconfig.json and bar/tsconfig.json
コマンドラインに渡すファイルの順序を心配する必要はありません。tscは、依存関係が常に最初にビルドされるように、必要に応じてそれらを並べ替えます。
tsc -bに固有のフラグもいくつかあります。
--verbose:何が起こっているかを説明するために詳細なログを出力します(他のフラグと組み合わせることができます)--dry:何が行われるかを示しますが、実際には何もビルドしません--clean:指定されたプロジェクトの出力を削除します(--dryと組み合わせることができます)--force:すべてのプロジェクトが最新でないかのように動作します--watch:ウォッチモード(--verboseを除くフラグと組み合わせることはできません)
注意点
通常、tscはnoEmitOnErrorがオンになっていない限り、構文エラーまたは型エラーがある場合でも出力(.jsおよび.d.ts)を生成します。増分ビルドシステムでこれを行うことは非常に悪いです。最新ではない依存関係の1つに新しいエラーが発生した場合、後続のビルドで最新のプロジェクトのビルドがスキップされるため、1回しか表示されません。このため、tsc -bは、すべてのプロジェクトでnoEmitOnErrorが有効になっているかのように効果的に動作します。
ビルド出力(.js、.d.ts、.d.ts.mapなど)をチェックインする場合、ソースコントロールツールがローカルコピーとリモートコピーの間でタイムスタンプを保持するかどうかによっては、特定のソースコントロール操作後に--forceビルドを実行する必要がある場合があります。
MSBuild
msbuildプロジェクトがある場合は、次を追加してビルドモードを有効にできます。
xml<TypeScriptBuildMode>true</TypeScriptBuildMode>
projファイルに。これにより、自動インクリメンタルビルドとクリーンが有効になります。
tsconfig.json/-pと同様に、既存のTypeScriptプロジェクトのプロパティは尊重されません。すべての設定はtsconfigファイルを使用して管理する必要があります。
一部のチームは、tsconfigファイルがペアになっている管理対象プロジェクトと同じ暗黙的なグラフ順序を持つmsbuildベースのワークフローを設定しています。ソリューションがこのようである場合は、プロジェクト参照とともにtsc -pでmsbuildを引き続き使用できます。これらは完全に相互運用可能です。
ガイダンス
全体構造
tsconfig.jsonファイルが多くなると、通常は構成ファイルの継承を使用して、共通のコンパイラーオプションを集中管理します。これにより、複数のファイルを編集するのではなく、1つのファイルの設定を変更できます。
もう一つの良い習慣は、すべてのリーフノードプロジェクトへのreferencesを持ち、filesを空の配列に設定するだけの「ソリューション」tsconfig.jsonファイルを用意することです(そうしないと、ソリューションファイルがファイルの二重コンパイルを引き起こすため)。3.0以降では、tsconfig.jsonファイルに少なくとも1つのreferenceがある場合、空のfiles配列を持つことはエラーではなくなったことに注意してください。
これにより、単純なエントリポイントが提供されます。例えば、TypeScriptリポジトリでは、src/tsconfig.jsonにすべてのサブプロジェクトをリストしているため、すべてのエンドポイントをビルドするために単純にtsc -b srcを実行します。
これらのパターンはTypeScriptリポジトリで見ることができます。主要な例としてsrc/tsconfig_base.json、src/tsconfig.json、およびsrc/tsc/tsconfig.jsonを参照してください。
相対モジュール用の構造化
一般的に、相対モジュールを使用しているリポジトリの移行には多くのことは必要ありません。指定された親フォルダの各サブディレクトリにtsconfig.jsonファイルを配置し、プログラムの意図されたレイヤーに合わせて、これらの構成ファイルへのreferenceを追加するだけです。 outDirを出力フォルダの明示的なサブフォルダに設定するか、rootDirをすべてのプロジェクトフォルダの共通ルートに設定する必要があります。
outFiles用の構造化
outFileを使用したコンパイルのレイアウトは、相対パスがあまり重要ではないため、より柔軟です。留意すべきことの1つは、一般的に「最後」のプロジェクトまでprependを使用しないことです。これにより、ビルド時間が改善され、特定のビルドに必要なI/O量が削減されます。TypeScriptリポジトリ自体がここでの良い参考になります。いくつかの「ライブラリ」プロジェクトといくつかの「エンドポイント」プロジェクトがあります。「エンドポイント」プロジェクトは可能な限り小さく保たれ、必要なライブラリのみをプルインします。