TypeScript 編譯性能優化:Project Reference

TypeScript 給 JavaScript 添加了一套類型系統,可以在編譯期間檢查出類型錯誤,這增加了代碼的健壯性,但也多了一個編譯的過程。

ts 編譯速度與項目規模有關,如果項目比較大,代碼很多,那就需要編譯很長一段時間。

有沒有什麼辦法可以提升 tsc 編譯的性能呢?

還真有,TypeScript 3.0 的時候實現了 Project Reference 的特性,就是用於優化編譯和類型檢查的性能的。

那 Project Reference 是幹什麼的呢?

Project Reference

想象這樣一個場景。項目目錄下有兩個相對獨立的模塊 aaa 和 bbb

它們是用同一個 tsconfig.json 來配置編譯方式的:

執行 tsc 就會編譯所有 include 的文件到 dist 目錄下:

假設 aaa 和 bbb 都很大,編譯要很久,但是兩者的關聯還不是特別大。

aaa 模塊下的變動基本和 bbb 模塊下的沒啥關係,但是 aaa 變了,bbb 也要重新編譯一遍,bbb 變了 aaa 也要重新編譯一遍,這就很沒必要。

有的同學說,那在 aaa 和 bbb 下分別放一個 tsconfig.json,各自編譯各自的不就行了?

這樣是可以,但是這樣就是多次編譯了,比較麻煩。

能不能還是一次編譯,但是對一些相對獨立的模塊做下緩存,不要跟隨別的模塊一起編譯呢?

可以的,這就是 Project Reference 做的事情了。

在 aaa 和 bbb 下各自創建一個 tsconfig.json,放各自的編譯配置。注意這裏要加一個 composite: true,這是 Project Reference 需要的:

然後在根目錄的 tsconfig.json 里加上一個 references 的配置,引入 aaa 和 bbb:

這樣再執行 tsc --build 進行編譯,你會發現編譯結果多了 .d.ts 的聲明,還多了 tsconfig.tsbuildinfo 的文件:

打開 tsconfig.tsbuildinfo 看一下,會發現它記錄了編譯了哪些文件,還記錄了這些文件的 hash 值:

看到這裏,你是不是就知道爲啥它能實現緩存了?

沒錯,就是對比文件的 hash,當編譯到這個 project 的時候,會對比下 hash 有沒有變化,變了纔去編譯。沒變的就直接跳過了。

而且,別的地方可能用到這個 project 的類型,所以需要生成 d.ts 聲明文件,這就是爲啥我們沒有指定 declaration: true 的配置,但是編譯產物裏還是有 d.ts。其實這是 composite 選項做的,它設置了 Project Reference 需要的一些編譯選項:

現在當你修改了 aaa 下某個模塊的代碼,重新編譯的時候就不會編譯 bbb 了,只會編譯 aaa 下的那個模塊。

這就是 Project Reference 的作用。

當然,這種編譯模式和常規的編譯模式不同,所以不是直接用 tsc 來編譯,而是用 tsc --build 或者 tsc -b。

此外,Project Reference 還支持通過 prepend 指定編譯順序,比如給 bbb 添加 prepend: true,那麼就會先編譯 bbb,再編譯當前項目,然後編譯 aaa:

其實很容易想到,monorepo 裏就可以用 Project Reference 來提升 tsc 的編譯性能。因爲 monorepo 下的多個 project 相互之間都比較獨立,一個模塊的改動一般不會影響另一個模塊,所以編譯的時候也應該各自做緩存。

總結

TypeScript 3.0 時實現了 Project Reference 來優化性能。

如果項目下有一些相對獨立的模塊,別的模塊的變動不影響它,但是它卻要跟着重新編譯一次,這時就可以用 Project Reference 來優化了。

在獨立的模塊下添加 tsconfig.json,加上 composite 的編譯選項,在入口的 tsconfig.json 裏配置 references 引用這些獨立的模塊。然後執行 tsc --build 或者 tsc -b 來編譯。

這時候就實現了編譯和類型檢查的性能優化。

原理是編譯時會生成 tsconfig.tsbuildinfo 的文件,記錄着編譯的文件和它們的 hash,當再次編譯的時候,如果文件 hash 沒變,那就直接跳過,從而提升了編譯速度。

這是 TypeScript 提供的編譯性能優化機制,當項目比較大,tsc 執行的速度比較慢的時候,不妨嘗試一下。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/IJYWOWHWGZSLQT9SukThlA