项目引用

项目引用是 TypeScript 3.0 引入的功能,允许将 TypeScript 项目分割成多个子项目。项目引用支持增量编译,提高大型项目的构建速度。

什么是项目引用

项目引用允许一个 TypeScript 项目引用另一个 TypeScript 项目。被引用的项目会被单独编译,生成声明文件供引用项目使用。

{
  "references": [
    { "path": "./shared" },
    { "path": "./app" }
  ]
}

配置项目引用

被引用项目配置

被引用项目需要设置 composite: true

{
  "compilerOptions": {
    "composite": true,
    "declaration": true,
    "declarationMap": true,
    "outDir": "./dist",
    "rootDir": "./src"
  }
}

composite: true 确保项目可以被引用。

引用项目配置

引用项目使用 references 字段。

{
  "references": [
    { "path": "../shared" }
  ],
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src"
  }
}

项目引用的优势

项目引用有以下优势:

  • 增量编译:只编译修改的项目
  • 代码隔离:项目之间边界清晰
  • 并行编译:多个项目可以并行编译
  • 类型检查优化:减少类型检查范围

项目结构

一个典型的项目引用结构:

project/
├── shared/
│   ├── tsconfig.json
│   └── src/
│       └── index.ts
├── app/
│   ├── tsconfig.json
│   └── src/
│       └── index.ts
└── tsconfig.json

根配置

根目录的 tsconfig.json 配置所有子项目。

{
  "references": [
    { "path": "./shared" },
    { "path": "./app" }
  ],
  "files": []
}

shared 项目配置

{
  "compilerOptions": {
    "composite": true,
    "declaration": true,
    "declarationMap": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"]
}

app 项目配置

{
  "references": [
    { "path": "../shared" }
  ],
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"]
}

使用引用项目

在 app 项目中使用 shared 项目。

import { greet } from "@shared"

console.log(greet("张三"))

需要在 tsconfig.json 中配置路径映射。

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@shared": ["../shared/src"]
    }
  }
}

增量编译

项目引用支持增量编译。使用 tsc -b 命令构建项目。

tsc -b

增量编译只编译修改的项目及其依赖。

前置依赖

references 中的 prepend 选项可以将引用项目的输出添加到当前项目的输出中。

{
  "references": [
    { "path": "../shared", "prepend": true }
  ]
}

prepend 适用于需要单一输出文件的场景。

解决方案模式

解决方案模式使用一个根 tsconfig.json 管理多个子项目。

{
  "files": [],
  "references": [
    { "path": "./shared" },
    { "path": "./app" },
    { "path": "./server" }
  ]
}

IDE 会自动识别解决方案模式,提供更好的开发体验。

实际应用

一个前后端分离的项目结构。

project/
├── shared/
│   ├── tsconfig.json
│   └── src/
│       └── types.ts
├── frontend/
│   ├── tsconfig.json
│   └── src/
│       └── main.ts
├── backend/
│   ├── tsconfig.json
│   └── src/
│       └── server.ts
└── tsconfig.json

根配置

{
  "files": [],
  "references": [
    { "path": "./shared" },
    { "path": "./frontend" },
    { "path": "./backend" }
  ]
}

shared 配置

{
  "compilerOptions": {
    "composite": true,
    "declaration": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"]
}

frontend 配置

{
  "references": [
    { "path": "../shared" }
  ],
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "lib": ["ES2020", "DOM"],
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"]
}

backend 配置

{
  "references": [
    { "path": "../shared" }
  ],
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"]
}

小结

项目引用允许将 TypeScript 项目分割成多个子项目。被引用项目需要设置 composite: true。项目引用支持增量编译、代码隔离和并行编译。解决方案模式使用根配置管理多个子项目。项目引用适用于大型项目和前后端分离的项目结构。