探究 tsconfig.node.json 文件和 references 字段的作用

13,628 阅读3分钟

起因经过

在使用 Vite 创建 vue-ts 模板的项目时,会发现除了 tsconfig.json 外,还有一个 tsconfig.node.json 文件。同时在 tsconfig.json 中有这样一段对我来说比较陌生的代码:

{
    "references": [{ "path": "./tsconfig.node.json" }]
}

于是想研究一下 tsconfig.node.json 文件和 references 字段究竟有什么作用。

在查阅了 相关文档 后,得知这是 TypeScript 3.0 新增的 “项目引用(Project References)” 功能,它允许用户为项目的不同部分使用不同的 TypeScript 配置。

然后打开 tsconfig.node.json 文件,其内容如下:

{
  "compilerOptions": {
    "composite": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}

注意到 "include": ["vite.config.ts"] 这段代码,它说明 tscnofig.node.json 是专门用于 vite.config.ts 这一文件的 TypeScript 配置文件。

那为什么 vite.config.ts 需要一份单独的配置文件呢?我的理解是因为运行环境的不同。

项目中的普通代码是运行在浏览器环境中的,因此 TypeScript 需要为这些代码提供 DOM 等浏览器接口的类型支持。而 vite.config.ts 是运行在 Node 环境中的,它不应访问浏览器接口,而相应地它需要各种 Node 接口的类型支持,因此两份代码理应使用不同的配置文件。

搞清楚基本原理后,下面再看看两份配置文件究竟有什么不同。

对比两份配置的具体差异

在使用 Vite 的 vue-ts 模板创建的项目中,tsconfig.json 文件中的 compilerOptions 字段内容如下:

"compilerOptions": {
  "target": "ESNext", // 将代码编译为最新版本的 JS
  "useDefineForClassFields": true, // 使用 Object.defineProperty 定义 class 中的属性,而非使用 obj.key = value 的形式定义属性
  "module": "ESNext", // 使用 ES Module 格式打包编译后的文件
  "moduleResolution": "Node", // 使用 Node 的模块解析策略
  "strict": true, // 启用所用严格的类型检查
  "jsx": "preserve", // 保留原始的 JSX 代码,不进行编译
  "sourceMap": true, // 生成 sourceMap 文件
  "resolveJsonModule": true, // 允许引入 JSON 文件
  "isolatedModules": true, // 该属性要求所有文件都是 ES Module 模块。
  "esModuleInterop": true, // 允许使用 import 引入使用 export = 导出的内容
  "lib": ["ESNext", "DOM"], // 引入 ES 最新特性和 DOM 接口的类型定义
  "skipLibCheck": true // 跳过对 .d.ts 文件的类型检查
},

tsconfig.node.json 中的 compilerOptions 字段内容如下:

"compilerOptions": {
  "composite": true, // 对于引用项目必须设置该属性
  "module": "ESNext",
  "moduleResolution": "Node",
  "allowSyntheticDefaultImports": true // 允许使用 import 导入使用 export = 导出的默认内容 
},

可以发现,tsconfig.node.jsontsconfig.json 少了不少选项,这基本是因为 vite.config.ts 中的代码较为简短,无需用到这些特性。

例如 vite.config.ts 文件不需要打包构建,因此无需设置 targetsourceMap 等属性。且该文件仅运行在 Node 环境中,因此不需要设置 lib: ["DOM"] 属性等等。

实际上除了 composite": true 字段是必须的外,其他字段都应根据文件的实际情况进行设置。如果后续要在 vite.config.ts 中添加更多复杂代码,可能就需要修改 tsconfig.node.json 中的配置。

如果以后需要在项目中添加仅在 Node 环境中运行的代码,直接修改 tsconfig.node.json 中的 include 字段即可。如果有其他特殊的配置需求,也可单独写一份配置文件然后添加到 tsconfig.jsonreferences 字段中。

总结

  • tsconfig.node.json 是专门用于 vite.config.ts 的 TypeScript 配置文件。
  • tsconfig.json 文件通过 references 字段引入 tsconfig.node.json 中的配置。
  • 使用 references 字段引入的配置文件需要设置 composite: true 字段,并用 includefiles 等等属性指明配置覆盖的文件范围。

至此,tsconfig.node.jsonreferences 字段的作用就基本弄清了。

如有疏漏,恳请指正。