Featured image of post TypeScript 项目参考:扩展大型代码库Featured image of post TypeScript 项目参考:扩展大型代码库

TypeScript 项目参考:扩展大型代码库

用于扩展大型代码库的 TypeScript 项目参考。组合项目、构建模式、增量构建、单一存储库集成和 CI 优化。

介绍

随着 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: truerootDiroutDir。强烈建议启用 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 中声明引用
涡轮增压通过 inputsdependsOn 提供本机支持
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 设置中更加强大。