TypeScript 3.0 的 References 工程引用 和 --build 模式
TypeScript 3.0 引入了 References 工程引用 和 --build 模式,这些功能为大型项目和复杂架构提供了强大的工具。通过这些功能,你可以将一个 TypeScript 项目拆分成多个子项目(模块),并且能够更高效地进行增量编译和构建。
Vite 项目中 tsconfig.json、tsconfig.app.json 和 tsconfig.node.json 的结构
使用npm init vite@latest创建的 Vue3 项目中,会有3个tsconfig.json文件。tsconfig.json、tsconfig.app.json 和 tsconfig.node.json 通常用于区分不同的环境配置,提高可维护性和灵活性。这种结构一般用于区分 前端(应用层) 和 后端(Node.js 层),或者在构建和开发阶段分别使用不同的配置。
1. 各个配置文件的含义
✅ 1.1 tsconfig.json主配置文件
- 示例:
1 2 3 4 5 6 7 8
| { "files": [], "references": [ { "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" } ] }
|
files:这个配置文件没有直接列出任何文件,主要通过 references 来引用其他配置文件。
references:指定了 tsconfig.app.json 和 tsconfig.node.json 作为依赖,确保这些文件中的配置会被合并并执行。
✅ 1.2 tsconfig.app.json
用于前端应用配置,支持 Vue 3 和 TypeScript,启用了严格模式和增量编译。
- 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| { "extends": "@vue/tsconfig/tsconfig.dom.json", "compilerOptions": { "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true }, "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] }
|
extends:继承了 @vue/tsconfig/tsconfig.dom.json,这是 Vue 官方推荐的基础配置,专为 Vue 3 项目定制,提供了对 Vue 文件的支持。
compilerOptions.tsBuildInfoFile:指定了 TypeScript 构建的增量编译信息文件位置,这对于快速的增量构建非常重要。
#### ✅ 1.3 tsconfig.node.json
用于 Node.js 环境的配置,针对 Vite 和服务器端代码优化了 TypeScript 设置。这里是指vite打开的本地服务器。
- 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| { "compilerOptions": { "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "target": "ES2022", "lib": ["ES2023"], "module": "ESNext", "skipLibCheck": true,
"moduleResolution": "bundler", "allowImportingTsExtensions": true, "isolatedModules": true, "moduleDetection": "force", "noEmit": true,
"strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true }, "include": ["vite.config.ts"] }
|
为什么要拆分多个配置文件?
- 环境差异
- 前端和后端使用不同的模块系统(
ESModules vs CommonJS)。
- 需要不同的构建工具配置(如 Vite 和 Node.js)。
- 构建效率
这种配置文件结构有助于保持前后端代码独立,并通过增量编译提高构建效率。
使用 --build 和 References 工程引用 的优势
1. 大型单体仓库(Monorepo)
- 场景:多个前端项目或子模块共享公共库、工具函数或组件库。
例如,一个大型电商平台可能有多个独立模块(用户管理、订单管理、支付系统等),但共享一些公共组件库或工具包。
- 优势:
- 每个子项目或库有独立的
tsconfig.json,并通过 references 配置管理依赖。
- 使用
--build 增量构建,避免全局重新编译,提高构建效率。
- 清晰的依赖关系和编译边界,减少编译时间。
2. 多包项目(例如 npm 包开发)
- 场景:开发多个 npm 包,每个包都有独立的
tsconfig.json,但共享通用的类型定义或配置。
例如,一个 UI 组件库,将不同的组件分为独立的包(如按钮、表格、下拉菜单),但共享公共类型定义。
- 优势:
- 每个包可以独立发布和版本管理。
- 通过
--build 和 references 配置,进行依赖管理和高效增量构建。
使用 project references 示例
项目结构
1 2 3 4 5 6 7 8
| /my-project /module-a tsconfig.json index.ts /module-b tsconfig.json index.ts tsconfig.json
|
主项目 tsconfig.json
在主项目的 tsconfig.json 中,启用 composite,并使用 references 来引用各个子模块(如 module-a 和 module-b)。
1 2 3 4 5 6 7 8
| { "files": [], "references": [ { "path": "./module-a" }, { "path": "./module-b" } ] }
|
- **
composite**:启用增量编译。
- **
references**:指定模块的依赖关系,TypeScript 会按顺序编译这些模块。
module-a 的 tsconfig.json
1 2 3 4 5 6 7 8 9
| { "extends": "../tsconfig.base.json", "compilerOptions": { "rootDir": ".", "outDir": "../dist/module-a" }, "include": ["index.ts"] }
|
- **
rootDir**:指定源代码的根目录。
- **
outDir**:编译输出目录。
- **
include**:指定要编译的文件。
module-a/index.ts
1 2 3 4
| export function add(a: number, b: number): number { return a + b; }
|
module-b 的 tsconfig.json
module-b 引用了 module-a,这意味着在编译 module-b 时,module-a 会先被编译。
1 2 3 4 5 6 7 8 9 10 11 12
| { "extends": "../tsconfig.base.json", "compilerOptions": { "outDir": "../dist/module-b", "rootDir": "." }, "include": ["index.ts"], "references": [ { "path": "../module-a" } ] }
|
module-b/index.ts
1 2 3 4 5 6
| import { add } from "../module-a/index.js";
export function calculate(a: number, b: number): number { return add(a, b) * 2; }
|
构建并运行
- 使用
tsc --build 命令进行构建:
- 运行编译后的代码:
1
| node dist/module-b/index.js
|
控制台输出
结论
- 使用 References 工程引用 和
--build 模式 可以极大提升大型 TypeScript 项目的编译效率,特别是在多模块或多包的情况下。
- Vite创建的Vue项目中会有三个tsconfig,
tsconfig.json、tsconfig.app.json 和 tsconfig.node.json 的拆分,可以帮助区分不同环境的 TypeScript 配置,确保不同环境下的编译需求和工具设置不冲突。