轉(zhuǎn)發(fā) # TypeScript項(xiàng)目引用(project references)
TypeScript新特性之項(xiàng)目引用(project references)
項(xiàng)目引用是TypeScript 3.0中的一項(xiàng)新功能,允許您將TypeScript程序構(gòu)建為更小的部分。
通過(guò)這樣做,您可以大大縮短構(gòu)建時(shí)間,實(shí)現(xiàn)組件之間的邏輯分離,并以新的更好的方式組織代碼。
我們還為tsc引入了一種新模式,即--build標(biāo)志,它與項(xiàng)目引用協(xié)同工作,以實(shí)現(xiàn)更快的TypeScript構(gòu)建。
示例項(xiàng)目
讓我們看一個(gè)相當(dāng)正常的程序,看看項(xiàng)目引用如何幫助我們更好地組織它。
想象一下,你有一個(gè)項(xiàng)目有兩個(gè)模塊,轉(zhuǎn)換器和單元,以及每個(gè)模塊的相應(yīng)測(cè)試文件:
/src/converter.ts
/src/units.ts
/test/converter-tests.ts
/test/units-tests.ts
/tsconfig.json
測(cè)試文件導(dǎo)入實(shí)現(xiàn)文件并進(jìn)行一些測(cè)試:
// converter-tests.ts
import * as converter from "../converter";
assert.areEqual(converter.celsiusToFahrenheit(0), 32);
以前,如果您使用單個(gè)tsconfig文件,則此結(jié)構(gòu)很難處理:
- 實(shí)現(xiàn)文件可以導(dǎo)入測(cè)試文件
- 在輸出文件夾名稱(chēng)中沒(méi)有出現(xiàn)src的情況下,無(wú)法同時(shí)構(gòu)建test和src,這可能是您不想要的
- 僅更改實(shí)現(xiàn)文件中的內(nèi)部結(jié)構(gòu)需要再次檢查測(cè)試,即使這不會(huì)導(dǎo)致新的錯(cuò)誤
- 僅更改測(cè)試需要再次對(duì)實(shí)現(xiàn)進(jìn)行檢查,即使沒(méi)有任何改變
您可以使用多個(gè)tsconfig文件來(lái)解決其中的一些問(wèn)題,但會(huì)出現(xiàn)新的問(wèn)題:
- 沒(méi)有內(nèi)置的最新檢查,因此您最終總是運(yùn)行兩次tsc
- 兩次調(diào)用tsc會(huì)導(dǎo)致更多的啟動(dòng)時(shí)間開(kāi)銷(xiāo)
- tsc -w無(wú)法一次在多個(gè)配置文件上運(yùn)行
項(xiàng)目引用(project references)可以解決所有這些問(wèn)題等等。
什么是項(xiàng)目引用(project references)?
tsconfig.json文件有一個(gè)新的頂級(jí)屬性"references"。
它是一個(gè)對(duì)象數(shù)組,指定要引用的項(xiàng)目:
{
"compilerOptions": {
// The usual
},
"references": [
{ "path": "../src" }
]
}
每個(gè)引用的path屬性可以指向包含tsconfig.json文件的目錄,也可以指向配置文件本身(可以具有任何名稱(chēng))。
當(dāng)您引用項(xiàng)目時(shí),會(huì)發(fā)生新的事情:
- 從引用的項(xiàng)目導(dǎo)入模塊將改為加載其輸出聲明文件(.d.ts)
- 如果引用的項(xiàng)目生成outFile,則輸出文件.d.ts文件的聲明將在此項(xiàng)目中可見(jiàn)
- 如果需要,構(gòu)建模式(下面會(huì)提到)將自動(dòng)構(gòu)建引用的項(xiàng)目
通過(guò)分成多個(gè)項(xiàng)目,您可以大大提高類(lèi)型檢查和編譯的速度,減少使用編輯器時(shí)的內(nèi)存使用量,并改進(jìn)程序邏輯分組的實(shí)施。
composite
引用的項(xiàng)目必須啟用新的composite設(shè)置。
需要此設(shè)置以確保TypeScript可以快速確定在何處查找引用項(xiàng)目的輸出。
啟用composite標(biāo)志會(huì)改變一些事情:
- rootDir設(shè)置(如果未顯式設(shè)置)默認(rèn)為包含tsconfig文件的目錄
- 所有實(shí)現(xiàn)文件必須由include模式匹配或在files數(shù)組中列出。如果違反此約束,tsc將通知您未指定哪些文件
- declaration必須打開(kāi)
declarationMaps
我們還增加了對(duì)declaration source maps的支持。如果啟用--declarationMap,您將能夠使用編輯器功能,如"轉(zhuǎn)到定義"和重命名,以在支持的編輯器中跨項(xiàng)目邊界透明地導(dǎo)航和編輯代碼。
以outFile為前綴
您還可以使用引用中的prepend選項(xiàng)啟用前置依賴(lài)項(xiàng)的輸出:
"references": [
{ "path": "../utils", "prepend": true }
]
預(yù)先設(shè)置項(xiàng)目將包括項(xiàng)目的輸出高于當(dāng)前項(xiàng)目的輸出。
這適用于.js文件和.d.ts文件,源代碼映射文件也將正確發(fā)出。
tsc只會(huì)使用磁盤(pán)上的現(xiàn)有文件來(lái)執(zhí)行此過(guò)程,因此可以創(chuàng)建一個(gè)項(xiàng)目,其中無(wú)法生成正確的輸出文件,因?yàn)槟承╉?xiàng)目的輸出將在結(jié)果文件中出現(xiàn)多次。
例如:
A
^ ^
/ \
B C
^ ^
\ /
D
在這種情況下,重要的是不要在每個(gè)參考文獻(xiàn)中添加前綴,因?yàn)樵贒的輸出中最終會(huì)得到兩個(gè)A副本 - 這可能會(huì)導(dǎo)致意外結(jié)果。
項(xiàng)目引用的注意事項(xiàng)
項(xiàng)目引用有一些您應(yīng)該注意的權(quán)衡。
因?yàn)橐蕾?lài)項(xiàng)目使用從其依賴(lài)項(xiàng)構(gòu)建的.d.ts文件,所以您必須在克隆之后簽入某些構(gòu)建輸出或構(gòu)建項(xiàng)目,然后才能在編輯器中導(dǎo)航項(xiàng)目而不會(huì)看到虛假錯(cuò)誤。
我們正在開(kāi)發(fā)一個(gè)能夠緩解這種情況的幕后.d.ts生成過(guò)程,但是現(xiàn)在我們建議告知開(kāi)發(fā)人員他們應(yīng)該在克隆之后構(gòu)建它們。
此外,為了保持與現(xiàn)有構(gòu)建工作流的兼容性,除非使用--build開(kāi)關(guān)調(diào)用,否則tsc不會(huì)自動(dòng)構(gòu)建依賴(lài)項(xiàng)。
讓我們了解更多關(guān)于--build的信息。
TypeScript的構(gòu)建模式
期待已久的功能是TypeScript項(xiàng)目的智能增量構(gòu)建。
在3.0中,您可以將-build標(biāo)志與tsc一起使用。
這實(shí)際上是tsc的新入口點(diǎn),其行為更像構(gòu)建協(xié)調(diào)器而不是簡(jiǎn)單的編譯器。
運(yùn)行tsc --build(簡(jiǎn)稱(chēng)tsc -b)將執(zhí)行以下操作:
- 查找所有引用的項(xiàng)目
- 檢測(cè)它們是否是最新的
- 按正確的順序構(gòu)建過(guò)時(shí)的項(xiàng)目
您可以為tsc -b提供多個(gè)配置文件路徑(例如tsc -b src test)。
就像tsc -p一樣,如果命名為tsconfig.json,則不需要指定配置文件名本身。
> tsc -b # 在當(dāng)前目錄中構(gòu)建tsconfig.json
> tsc -b src # 構(gòu)建src/tsconfig.json
> tsc -b foo/release.tsconfig.json bar # 構(gòu)建foo/release.tsconfig.json和構(gòu)建bar/tsconfig.json
不要擔(dān)心您在命令行上傳遞的排過(guò)序的文件 - 如果需要,tsc將重新排序它們,以便始終首先構(gòu)建依賴(lài)項(xiàng)。
還有一些特定于tsc -b的標(biāo)志:
--verbose: 打印詳細(xì)日志記錄以解釋正在發(fā)生的事情(可能與任何其他標(biāo)志組合)
--dry: 顯示將要完成的但實(shí)際上不構(gòu)建任何內(nèi)容
--clean: 刪除指定項(xiàng)目的輸出(可以與--dry結(jié)合使用)
--force: 就好像所有項(xiàng)目都已過(guò)時(shí)一樣
--watch: 監(jiān)視模式(除了--verbose外,不得與任何標(biāo)志組合使用)
注意事項(xiàng)
通常,除非出現(xiàn)noEmitOnError,否則tsc將在出現(xiàn)語(yǔ)法或類(lèi)型錯(cuò)誤時(shí)生成輸出(.js和.d.ts)。
在增量構(gòu)建系統(tǒng)中執(zhí)行此操作將非常糟糕 - 如果您的一個(gè)過(guò)時(shí)的依賴(lài)項(xiàng)出現(xiàn)新錯(cuò)誤,您只能看到它一次,因?yàn)楹罄m(xù)構(gòu)建將跳過(guò)構(gòu)建現(xiàn)在最新的項(xiàng)目。
因此,tsc -b實(shí)際上就像為所有項(xiàng)目啟用noEmitOnError一樣。
如果您檢查任何構(gòu)建輸出(.js,.d.ts,.d.ts.map等),您可能需要在某些源控制操作之后運(yùn)行--force構(gòu)建,具體取決于源控制工具是否保留
本地副本和遠(yuǎn)程副本之間的時(shí)間映射。
MSBuild
如果您有msbuild項(xiàng)目,則可以通過(guò)添加如下代碼到您的proj文件來(lái)啟用構(gòu)建模式
<TypeScriptBuildMode>true</TypeScriptBuildMode>
這將啟用自動(dòng)增量構(gòu)建和清潔。
請(qǐng)注意,與tsconfig.json/-p一樣,不會(huì)遵循現(xiàn)有的TypeScript項(xiàng)目屬性 - 應(yīng)使用tsconfig文件管理所有設(shè)置。
一些團(tuán)隊(duì)已經(jīng)設(shè)置了基于msbuild的工作流,其中tsconfig文件與他們配對(duì)的托管項(xiàng)目具有相同的隱式圖表排序。
如果您的解決方案是這樣的,您可以繼續(xù)使用msbuild和tsc -p以及項(xiàng)目引用;
這些是完全可互操作的。
指導(dǎo)(Guidance)
整體結(jié)構(gòu)
使用更多tsconfig.json文件,您通常需要使用配置文件繼承來(lái)集中您的常用編譯器選項(xiàng)。
這樣,您可以在一個(gè)文件中更改設(shè)置,而不必編輯多個(gè)文件。
另一個(gè)好的做法是擁有一個(gè)"解決方案"tsconfig.json文件,該文件只引用了所有l(wèi)eaf-node項(xiàng)目。
這提供了一個(gè)簡(jiǎn)單的切入點(diǎn);
例如,在TypeScript repo中,我們只運(yùn)行tsc -b src來(lái)構(gòu)建所有端點(diǎn),因?yàn)槲覀兞谐隽藄rc/tsconfig.json中的所有子項(xiàng)目。請(qǐng)注意,從3.0開(kāi)始,如果在tsconfig.json中至少有一個(gè)reference將不會(huì)針對(duì)空的files數(shù)組報(bào)錯(cuò)
您可以在TypeScript存儲(chǔ)庫(kù)中看到這些模式 - src/tsconfig_base.json,src/tsconfig.json和src/tsc/tsconfig.json作為關(guān)鍵示例。
構(gòu)建相關(guān)模塊
通常,使用相關(guān)模塊transition a repo并不需要太多。
只需將tsconfig.json文件放在給定父文件夾的每個(gè)子目錄中,并添加對(duì)這些配置文件的引用以匹配程序的預(yù)期分層。
您需要將outDir設(shè)置為輸出文件夾的顯式子文件夾,或?qū)ootDir設(shè)置為所有項(xiàng)目文件夾的公共根目錄。
構(gòu)建outFiles
使用outFile進(jìn)行編譯的布局更靈活,因?yàn)橄鄬?duì)路徑無(wú)關(guān)緊要。
要記住的一件事是,您通常希望在"最后"項(xiàng)目之前不使用前置 - 這將改善構(gòu)建時(shí)間并減少任何給定構(gòu)建中所需的I/O量。
TypeScript repo本身就是一個(gè)很好的參考 - 我們有一些"庫(kù)"項(xiàng)目和一些"端點(diǎn)"項(xiàng)目;
"端點(diǎn)"項(xiàng)目盡可能小,只吸引他們需要的庫(kù)。
原文地址:
http://www.typescriptlang.org/docs/handbook/project-references.html