文章目录
- 为什么需要三个配置文件?
- [tsconfig.json - 浏览器端的"宪法"](#tsconfig.json - 浏览器端的"宪法")
- [tsconfig.node.json - Node.js 的"专业宪法"](#tsconfig.node.json - Node.js 的"专业宪法")
- [vite.config.ts - 连接两端的"桥梁"](#vite.config.ts - 连接两端的"桥梁")
- 三者的协作关系
- 常见问题与解决方案
-
- 找不到模块 'vite'
- [VSCode 不识别 import.meta.env](#VSCode 不识别 import.meta.env)
- 构建时类型不匹配
- 实践总结
- 常见问题汇总
- 实用命令
- VSCode翻译插件
- 参考资料
为什么需要三个配置文件?
apps\web-antd\tsconfig.json
apps\web-antd\tsconfig.node.json
apps\web-antd\vite.config.ts
核心概念图
┌─────────────────────────────────────────────────────┐
│ 项目根目录 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌──────────────────────┐ │
│ │ tsconfig.json │ │ tsconfig.node.json │ │
│ │ (浏览器端) │◄───│ (Node.js端) │ │
│ │ │ │ │ │
│ │ 包含: src/**/* │ │ 包含: vite.config.ts│ │
│ └────────┬────────┘ └──────────┬───────────┘ │
│ │ │ │
│ │ 依赖关系 │ │
│ └────────────┬───────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │vite.config.ts│ │
│ │ (桥梁文件) │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────┘
tsconfig.json - 浏览器端的"宪法"
作用
比喻 :如果把项目比作一个国家,
tsconfig.json就是宪法------它定义了所有浏览器端代码的基本规则。
示例
apps\web-antd\tsconfig.json
json
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/web-app.json", // 继承基础配置
"compilerOptions": {
"paths": {
"#/*": ["./src/*"] // 路径别名:#/ → src/
}
},
"references": [{ "path": "./tsconfig.node.json" }], // 依赖 Node 配置
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
}
apps\web-antd\src\app.vue
typescript
import { antdLocale } from '#/locales';
关键配置项详解
| 配置项 | 含义 | 为什么这样设置? |
|---|---|---|
extends |
继承基础配置 | 避免重复编写通用配置(如 strict: true) |
paths |
路径别名 | #/utils 映射到 src/utils,让导入更简洁 |
references |
项目引用 | 告诉 TypeScript:"我需要 tsconfig.node.json 的类型" |
include |
包含文件 | 只处理 src/ 下的代码,不包含配置文件 |
tsconfig.node.json - Node.js 的"专业宪法"
为什么需要独立的 Node 配置?
比喻:就像一个公司有"国内市场部"和"国际市场部",虽然都是公司的一部分,但工作方式、工具、规则完全不同。
真实项目示例
json
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/node.json", // 继承 Node 基础配置
"compilerOptions": {
"composite": true, // 启用项目引用
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"noEmit": false // 需要生成类型文件
},
"include": ["vite.config.ts"] // 只包含配置文件
}
关键配置项对比
| 配置项 | tsconfig.json | tsconfig.node.json | 原因 |
|---|---|---|---|
lib |
["DOM", "ESNext"] |
["ESNext"] |
Node 环境没有 DOM |
types |
["vite/client"] |
["node"] |
需要 Node.js 类型 |
moduleResolution |
"bundler" |
"node" |
不同的模块解析方式 |
composite |
不需要 | 需要 | 作为被引用的项目 |
文件归属图
项目文件归属:
┌────────────────────────────────────────┐
│ tsconfig.json 负责: │
│ ├── src/ │
│ │ ├── App.vue │
│ │ ├── main.ts │
│ │ └── components/ │
│ └── 所有浏览器端代码 │
├────────────────────────────────────────┤
│ tsconfig.node.json 负责: │
│ ├── vite.config.ts │
│ ├── vitest.config.ts (如果有) │
│ └── 所有 Node.js 脚本 │
└────────────────────────────────────────┘
vite.config.ts - 连接两端的"桥梁"
三重视角
比喻 :
vite.config.ts就像一个"翻译官":
- 它用 Node.js 的语言(
tsconfig.node.json)编写- 它定义浏览器端的规则(影响
tsconfig.json)- 它连接两个世界
类型来源分析
typescript
import { defineConfig } from 'vite'
// ↑ 这个类型从哪里来?
// 1. tsconfig.node.json 中配置了 types: ["node"]
// 2. 所以能找到 @types/node 中的类型
// 3. vite 包自带类型定义
// 4. 浏览器端代码通过 references 共享这些类型
类型传递流程
vite.config.ts (Node.js 环境)
│
│ 1. 使用 Node.js 类型编译
▼
生成 .d.ts 类型文件 (通过 composite: true)
│
│ 2. 被 tsconfig.json 引用 (references)
▼
src/ 中的代码可以使用 Vite 的类型
│
│ 3. 例如 import.meta.env 的类型
▼
浏览器应用获得完整的类型提示
三者的协作关系
完整协作图
┌─────────────────────────────────────────────────────────────┐
│ 开发工作流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 开发者写代码 │
│ ↓ │
│ 编辑器中打开 .vue 文件 │
│ ↓ │
│ VSCode 读取 tsconfig.json │
│ ↓ │
│ 看到 references → 加载 tsconfig.node.json │
│ ↓ │
│ 读取 vite.config.ts 的类型信息 │
│ ↓ │
│ 为 import.meta.env 提供类型提示 │
│ ↓ │
│ 开发者获得完整的智能提示 ✅ │
│ │
└─────────────────────────────────────────────────────────────┘
依赖关系矩阵
| 文件 | 依赖 | 被依赖 | 作用 |
|---|---|---|---|
tsconfig.json |
tsconfig.node.json |
src/ 下的代码 |
定义浏览器编译规则 |
tsconfig.node.json |
@vben/tsconfig/node.json |
tsconfig.json、vite.config.ts |
定义 Node 编译规则 |
vite.config.ts |
tsconfig.node.json |
src/ 代码(通过类型传递) |
配置构建工具 |
构建顺序
执行 tsc --build 时:
第1步:构建 tsconfig.node.json
↓
生成 .tsbuildinfo 缓存
↓
第2步:构建 tsconfig.json
↓
使用前者的类型信息
↓
第3步:生成最终的类型文件
常见问题与解决方案
找不到模块 'vite'
错误现象:
typescript
// ❌ 在 src/ 中报错
import { defineConfig } from 'vite' // 找不到模块
原因 :src/ 使用的是浏览器配置,不包含 Node.js 类型。
解决方案:
json
// tsconfig.json 中添加 references
{
"references": [{ "path": "./tsconfig.node.json" }]
}
VSCode 不识别 import.meta.env
错误现象:
typescript
// ❌ 类型报错
const apiUrl = import.meta.env.VITE_API_URL
// Property 'VITE_API_URL' does not exist on type 'ImportMetaEnv'
原因 :缺少 vite/client 类型。
解决方案:
json
// tsconfig.json
{
"compilerOptions": {
"types": ["vite/client"] // 添加 Vite 客户端类型
}
}
构建时类型不匹配
错误现象:
error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'
原因:浏览器和 Node.js 对某些 API 的类型定义不同。
解决方案:
- 确保
tsconfig.json和tsconfig.node.json使用不同的lib - 使用
/// <reference types="..." />明确指定类型
实践总结
配置检查清单
markdown
☐ tsconfig.json
☐ 设置正确的 lib (DOM, ESNext)
☐ 配置 paths 别名
☐ 添加 references 指向 node 配置
☐ include 只包含 src/ 目录
☐ tsconfig.node.json
☐ 设置 composite: true
☐ 配置 types: ["node"]
☐ include 包含 vite.config.ts
☐ 设置正确的 moduleResolution
☐ vite.config.ts
☐ 使用 defineConfig
☐ 导出配置对象
☐ 类型由 tsconfig.node.json 提供
常见问题汇总
| 问题 | 答案 |
|---|---|
| 可以只用一个 tsconfig.json 吗? | 小项目可以,但大型项目需要分离 |
| references 中的路径怎么写? | 相对于当前文件的路径 |
| composite: true 是必须的吗? | 被引用的项目必须设置 |
| 如何调试配置问题? | 使用 tsc --showConfig 查看最终配置 |
| 生产环境需要这些配置文件吗? | 不需要,它们是开发时用的 |
实用命令
bash
# 查看最终配置
pnpm tsc --showConfig
# 检查类型(不输出文件)
pnpm tsc --noEmit
# 构建所有项目
pnpm tsc --build
# 构建特定项目
pnpm tsc --build tsconfig.node.json
# 清除缓存
rm -rf node_modules/.tmp/*.tsbuildinfo
VSCode翻译插件
Comment Translate
tencent-cloud-translate
参考资料
- TypeScript 官方文档 - 项目引用
- Vite 官方文档 - 配置
- TypeScript 配置参考
- apps\web-antd\tsconfig.json
- apps\web-antd\tsconfig.node.json
- apps\web-antd\vite.config.ts