介紹
隨著 TypeScript 程式碼庫的成長,單一的 tsconfig.json 方法會崩潰。每次呼叫 tsc 都會進行類型檢查並發出整個項目 - 即使在大型 monorepos 中使用 --noEmit ,這個過程也可能需要幾分鐘的時間。更糟的是,沒有模組邊界,任何文件都可以匯入任何其他文件,從而創建難以重構的混亂依賴關係圖。 TypeScript 專案參考 透過允許您將程式碼庫拆分為獨立的子專案(每個子專案都有自己的 tsconfig.json)來解決此問題,從而實現增量建置、強制執行 API 邊界以及顯著加快類型檢查速度。
什麼是項目參考?
專案引用聲明一個 TypeScript 專案依賴另一個專案。每個子項目必須在其 tsconfig.json 中設定 composite: true,並且使用項目在 references 數組中列出其依賴項:
{
"compilerOptions": {
"composite": true,
"declaration": true,
"declarationMap": true,
"rootDir": "src",
"outDir": "dist"
}
}
{
"references": [
{ "path": "../packages/core" },
{ "path": "../packages/utils" }
]
}
建置時,TypeScript 首先建構引用的項目(依拓樸順序),產生父專案使用的 .d.ts 和 .js 輸出。這強制了一個清晰的、非循環的依賴關係圖——如果套件 A 引用包 B,那麼 B 就不能引用 A。任何建立循環相依性的嘗試都會產生編譯時錯誤。
組合項目和建構模式
複合項目 (composite: true) 是設計供其他項目引用的項目。它需要 declaration: true、rootDir 和 outDir。強烈建議啟用 declarationMap: true — 它會產生 .d.ts.map 文件,允許編輯器工具(如「轉到定義」)直接導航到原始 .ts 來源而不是 .d.ts 聲明文件。
建置模式指令 tsc --build (或 tsc -b)智慧地處理整個專案圖:
# Build all projects and their dependencies
tsc -b
# Force rebuild all projects
tsc -b --force
# Clean build outputs
tsc -b --clean
# Dry run — show what would be built
tsc -b --dry
建置模式使用 .tsbuildinfo 檔案來追蹤檔案雜湊和依賴關係。在後續運行中,它會跳過輸入未更改的項目,導致大型 monorepos 的建置時間減少 50–90%。 incremental: true 選項由 composite 隱含,但您可以使用 tsBuildInfoFile 控制建置資訊檔案的寫入位置。
單一倉庫集成
專案參考與 monorepo 工具自然整合。典型的結構如下圖所示:
packages/
core/ tsconfig.json (composite: true)
utils/ tsconfig.json (composite: true)
apps/
web/ tsconfig.json (references: [core, utils])
api/ tsconfig.json (references: [core, utils])
tsconfig.base.json
不同的 monorepo 工具提供不同程度的支援:
| 工具 | 支援 |
|---|---|
| npm/pnpm/yarn 工作區 | 效果很好;在根 tsconfig.json 中聲明引用 |
| 渦輪增壓 | 透過 inputs 和 dependsOn 提供原生支援 |
| Nx | 自動偵測項目參考;並行化建置 |
| 勒納 | 需要手動設定 |
聲明圖和開發者經驗
最有影響力但未充分利用的功能之一是聲明映射。當您導航到消費者專案中的類型定義(例如,VS Code 的「轉到定義」)時,如果沒有聲明映射,您將進入 .d.ts 文件,該文件僅包含類型簽名,而不包含實作。使用 declarationMap: true,您可以直接跳到原始 .ts 來源:
{
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"sourceMap": true
}
}
聲明映射的運行時開銷為零——它們僅被編輯器工具消耗。與 sourceMap: true 相結合,它們提供了從開發到生產的完整偵錯體驗。
CI優化
項目參考的真正回報來自 CI。透過在運行之間快取 .tsbuildinfo 檔案(使用 @actions/cache 或類似檔案),您可以在管道執行之間保留增量建置資訊:
# GitHub Actions — cache .tsbuildinfo files
- uses: actions/cache@v3
with:
path: "**/*.tsbuildinfo"
key: tsbuildinfo-${{ runner.os }}-${{ hashFiles('**/tsconfig*.json') }}
對於選擇性類型檢查,請使用 tsc -b --noEmit — 此類型僅檢查自上次建置以來發生變更的項目,而不是整個程式碼庫。為主分支建置保留 --force ;依賴增量模式進行拉取請求 CI。對於非常大的單一儲存庫,像 nx affected 這樣的工具可以進一步將範圍縮小到受給定變更直接影響的項目。
結論
TypeScript 專案參考解決了大型 TypeScript 程式碼庫的擴充問題。首先將您的專案分成 2-3 個邏輯包 - 一個核心類型包、一個實用程式包和您的應用程式程式碼。將 composite: true 與聲明映射結合使用以獲得良好的開發人員體驗,利用 tsc -b 進行快速增量構建,並在 CI 中緩存 .tsbuildinfo 文件以跨管道運行擴展這些優勢。 Turborepo 和 Nx 等工具透過快取和並行執行增強項目引用,使它們在 monorepo 設定中更加強大。

