tsconfig.node.json 是 Vite 项目(尤其是你用 pnpm create vite 生成的模板)中专门为 Node.js 环境准备的 TypeScript 配置文件。
它和根目录下的 tsconfig.json 是一对 "双胞胎" ,分工明确:一个管前端页面(浏览器环境),一个管构建工具(Node 环境)。
下面我带你彻底搞清楚:它为什么存在 、里面写的是什么 ,以及它和主配置如何配合。
1. 为什么需要 tsconfig.node.json?(核心原理)
你的项目里有两个完全不同的 JavaScript 运行环境:
| 运行环境 | 对应的文件 | 能用的 API |
|---|---|---|
| 浏览器(前端) | src/*.vue、src/*.ts |
window、document、localStorage、alert |
| Node.js(工具链) | vite.config.ts、.eslintrc.cjs |
process.env、__dirname、fs(文件系统)、path 模块 |
如果你在 vite.config.ts 里写 document.getElementById,那完全没有意义(服务端哪来的 DOM?);同样,如果在 Vue 组件里写 process.env,Vite 会报错(浏览器不认识 process)。
所以,Vite 官方模板就把配置文件拆成了两个:
tsconfig.json:给src/下的前端代码用(眼里只有浏览器 API)。tsconfig.node.json:给根目录下的 Node 脚本用(眼里只有 Node API 和构建配置)。
2. 默认的 tsconfig.node.json 长什么样?(逐行拆解)
当你用 pnpm create vite 创建 Vue + TS 项目时,根目录会自动生成这个文件,内容通常如下:
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"strict": true
},
"include": ["vite.config.ts", "vitest.config.ts", "cypress.config.ts", "playwright.config.ts"]
}
看起来很短,但每个字段都有"专为 Node 设计"的深意:
① "composite": true(项目引用)
- 含义:开启"项目引用"模式。它告诉 TypeScript:"这个配置是一个独立的子项目"。
- 作用 :当你的主
tsconfig.json通过"references": [{ "path": "./tsconfig.node.json" }]引用它时,TS 可以精准地只编译vite.config.ts,而不会把 Vue 组件里的类型错误混在一起。这也是为什么有时你会看到根目录生成*.tsbuildinfo文件(增量编译缓存)。
② "module": "ESNext" 与 "moduleResolution": "bundler"
- 为什么不是 CommonJS? 虽然 Vite 配置文件运行在 Node 环境,但现代 Vite 默认使用 ES Module 格式(
package.json中"type": "module")。设为ESNext让 TS 知道我们写的是import/export语法,且由 Vite(或tsx)来解析。
③ "allowSyntheticDefaultImports": true
- 解决痛点 :允许你
import path from 'path'(没有* as)这种写法。Node 环境下path模块是 CommonJS 导出,这个选项让你写起来更舒服。
④ "include"(只包含配置文件)
- 重点关注 :这里只 包含
vite.config.ts以及测试框架(Vitest/Cypress)的配置文件。 - 故意排除 :它绝不包含
src/目录。这意味着当你编辑vite.config.ts时,TS 编译器不会 去检查src/里的 Vue 组件,编译速度极快。
3. 主 tsconfig.json 如何"拉上"它?(references 字段)
打开你的主 tsconfig.json(根目录那个大的),你会发现底部多了这几行:
{
"extends": "@vue/tsconfig/tsconfig.json",
"compilerOptions": { /* ... */ },
"include": ["src/**/*.ts", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }] // 👈 就是这一行!
}
references数组告诉 TS 编辑器(VSCode):"当我打开这个项目时,不仅要加载主配置,还要加载tsconfig.node.json,把它们视为同一个完整的项目。"- 效果 :你在 VSCode 里点击
vite.config.ts中的某个类型(比如defineConfig),可以完美跳转;且在src/里写代码时,不会因为vite.config.ts的类型错误而报红(隔离得很好)。
4. 对比总结:tsconfig.json vs tsconfig.node.json
| 对比维度 | 主 tsconfig.json |
tsconfig.node.json |
|---|---|---|
| 服务对象 | src/ 下的 Vue 组件和工具函数 |
根目录的 vite.config.ts 等构建脚本 |
| 运行环境 | 浏览器(DOM) | Node.js(服务端) |
lib 包含 |
["DOM", "ES2020"] |
隐式不含 DOM(写 window 会报错) |
noEmit |
通常为 true(让 Vite 打包) |
不一定设置,但 composite 开启时会有缓存 |
是否检查 .vue |
✅ 是(include 包含 *.vue) |
❌ 否(绝对不能包含,否则会编译 Vue 模板报错) |
5. 实战场景:当你需要修改 vite.config.ts 时
比如你想在配置里读取环境变量:
// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
// 这里会用到 Node 的 process.cwd(),tsconfig.node.json 认识它
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), 'VITE_')
// ...
})
如果你不小心在 vite.config.ts 里写了个浏览器 API:
const el = document.querySelector('#app') // ❌ tsconfig.node.json 会报红!
因为 tsconfig.node.json 没有包含 DOM 类型库,VSCode 会立刻提醒你"找不到 document",防止你写出跑不起来的代码。
6. Windows 11 下的注意事项
- 路径写法 :
"path": "./tsconfig.node.json"用正斜杠/,Windows 下完全兼容。 - 换行符 :和之前一样,建议保持
LF格式(VSCode 右下角可切换),避免某些旧版 TS 解析 BOM 头异常。
7. 如果你用 @vue/tsconfig 包(推荐做法)
其实官方推荐直接继承社区包,这样你根本不用手动维护这两个文件的基础选项:
// tsconfig.json
{
"extends": "@vue/tsconfig/tsconfig.json",
"compilerOptions": { /* 只写别名和路径 */ },
"references": [{ "path": "./tsconfig.node.json" }]
}
// tsconfig.node.json
{
"extends": "@vue/tsconfig/tsconfig.json",
"compilerOptions": { "composite": true },
"include": ["vite.config.ts"]
}
一句话总结记忆
tsconfig.node.json是给 Vite 配置文件(vite.config.ts)戴的"专属眼镜" ,戴上它,TypeScript 只认 Node.js 的 API 和构建工具语法,绝不把浏览器里的window和document混进来。
现在打开你项目的根目录,看一下有没有 tsconfig.node.json 和 references 字段。如果没有,赶紧补上,VSCode 的智能提示会更精准!有任何配置报错,随时截图问我 😄