Typescript: 项目引用

644 阅读3分钟

随着应用的增长,TSC对代码做类型检查和编译所用的时间将越来越长。花费在类型检查和编译上的时间几乎与代码的体量呈线性关系。在本地开发过程中,逐渐增多的编译时间将严重拖慢开发效率。

为了解决这个问题,TSC内置了一个成为“项目引用”(project references)的功能,能显著减少编译耗时。若项目中有上百个文件,建议可以使用下项目引用。

在 TypeScript 3.0 及更高版本中,可以使用 tsconfig.json 文件中的 references 属性来设置项目引用。例如,假设有两个 TypeScript 项目,一个是主项目,一个是库项目,它们的目录结构如下:

project/
├── main/
│   ├── tsconfig.json
│   ├── src/
│   └── ...
└── lib/
    ├── tsconfig.json
    ├── src/
    └── ...

可以将 lib 项目作为 main 项目的依赖项,通过以下方式配置:

  1. 在 lib 项目的 tsconfig.json 文件中设置 composite 属性为 true,以启用项目引用:
{
  "compilerOptions": {
    "composite": true,
    "outDir": "dist",
    "declaration": true,
    "declarationMap": true,
    "rootDir": "."
  },
  "include": ["src/**/*.ts"]
}
  1. 在 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
    ]
}