随着应用的增长,TSC对代码做类型检查和编译所用的时间将越来越长。花费在类型检查和编译上的时间几乎与代码的体量呈线性关系。在本地开发过程中,逐渐增多的编译时间将严重拖慢开发效率。
为了解决这个问题,TSC内置了一个成为“项目引用”(project references)的功能,能显著减少编译耗时。若项目中有上百个文件,建议可以使用下项目引用。
在 TypeScript 3.0 及更高版本中,可以使用 tsconfig.json 文件中的 references 属性来设置项目引用。例如,假设有两个 TypeScript 项目,一个是主项目,一个是库项目,它们的目录结构如下:
project/
├── main/
│ ├── tsconfig.json
│ ├── src/
│ └── ...
└── lib/
├── tsconfig.json
├── src/
└── ...
可以将 lib 项目作为 main 项目的依赖项,通过以下方式配置:
- 在 lib 项目的 tsconfig.json 文件中设置 composite 属性为 true,以启用项目引用:
{
"compilerOptions": {
"composite": true,
"outDir": "dist",
"declaration": true,
"declarationMap": true,
"rootDir": "."
},
"include": ["src/**/*.ts"]
}
- 在 main 项目的 tsconfig.json 文件中设置 references 属性,引用 lib 项目:
{
"references": [
{
"path": "../lib",
“prepend”: true
}
],
"compilerOptions": {
"outDir": "dist",
"baseUrl": ".",
"paths": {
"my-lib": ["../lib/src"]
}
},
"include": ["src/**/*.ts"]
}
上面关键的设置是:
- composite: 告诉TSC,这个文件是一个大型TypeScript项目的子项目。
- declaration: 告诉TSC,为这个子项目生成.d.ts声明文件。在项目引用中,子项目可以访问各子项目的声明文件和生成的JavaScript,但是不能访问TypeScript源文件。这就划定了一条界限,TSC不会再重新检查或编译代码:如果更新子项目A中的一行代码,TSC不会对子项目B重新做类型检查和编译;TSC所要做的只是检查B的类型声明中有没有类型错误。这个行为是项目引用在重新构建大型项目用时较少的关键。
- declarationMap: 告诉TSC,为生成的类型声明构建源码映射。
- references: 在一个数组中列出该项目依赖的其他子项目。每个引用的path字段要指向一个内有tsconfig.json文件的文件夹,或者直接指向一个TSC配置文件(如果配置文件的名称不是tsconfig.json).
prepend
字段指明把所引用的子项目生成的JavaScript和源码映射与当前项目生成的JavaScript和源码映射拼接在一起。注意:prepend只在使用outFile时有用,如未使用outFile,可以不设置prepend
。 - rootDir: 明确指明该子项目应该相对根项目(.)编译。另一种做法是设置outDir,指向根项目的outDir中的一个子文件夹。
通过上面的设置,可以在 main 项目中使用以下方式引用 lib 项目中的代码:
import { myFunction } from 'my-lib/myModule';
在编译 main 项目时,TypeScript 会自动编译 lib 项目并解决依赖关系,确保生成的 JavaScript 文件包含了 lib 项目中的代码。
使用extends减少tsconfig.json中的样板代码量
有时,所有子项目的编译器选项是一样的。这种情况下,最好在根目录中创建一个基本的tsconfig.json文件,让子项目的tsconfig.json文件在此基础扩展:
{
"compilerOptions": {
"composite": true,
"declaration": true,
"declarationMap": true,
"lib": ["es2015", "es2016.array.include"],
rootDir: ".",
"sourceMap": true,
"strict": true,
"target": "es5"
}
}
然后更新子项目的tsconfig.json文件,使用extends选项扩展:
{
"extends": "../tsconfig.base",
"include": [
"./**/*.ts"
],
"references": [
"path": "../myReferencedProject",
"prepend": true
]
}