tsserver
在 VS Code 里,TypeScript/JavaScript 的智能提示、跳转、报错检查这些功能,都是靠 tsserver(TypeScript Server)驱动的。它的工作方式可以分为几个层面来看:
1. tsserver 是什么
tsserver
是 TypeScript 编译器 (tsc
) 提供的一个 长期运行的语言服务进程。- 它和
tsc
共享同一套编译、类型检查逻辑,但不是一次性编译退出,而是作为一个 服务端 持续运行,响应 VS Code 等客户端发来的请求。 - 通过 JSON-RPC 协议 与编辑器通信。
2. 启动过程
- 当你在 VS Code 打开一个含有 JS/TS 文件的工作区时,VS Code 的 TypeScript 扩展 会启动一个
tsserver
进程。 - 启动时会根据
tsconfig.json
/jsconfig.json
初始化项目配置(如果没有配置,就以默认模式运行)。
3. 工作原理
-
文件同步
- 编辑器把当前打开的文件内容同步给
tsserver
(包括你还没保存的改动)。 - 同时告诉它项目结构(有哪些文件、模块路径等)。
- 编辑器把当前打开的文件内容同步给
-
请求/响应模式
-
编辑器发送请求,比如:
completion
→ 请求补全建议quickinfo
→ 请求符号的 hover 信息definition
→ 请求跳转到定义references
→ 查找引用
-
tsserver
返回 JSON 格式的结果,VS Code 插件渲染成你看到的提示/导航。
-
-
增量更新
- 当文件发生修改时,VS Code 只会通知
tsserver
哪些部分变了。 tsserver
内部维护一份 AST(抽象语法树)+ 类型检查结果,可以做增量更新,不必重头编译。
- 当文件发生修改时,VS Code 只会通知
-
语言服务
-
tsserver
使用 TypeScript 编译器 API 提供高级功能:- 代码补全:基于 AST + 类型信息推断可能的成员/变量。
- 错误提示:运行类型检查规则,给出诊断信息。
- 重构 / 重命名:通过符号表找到受影响的引用并更新。
- 导航:符号定义、实现、调用链等。
-
4. 项目和配置管理
tsserver
会探测项目边界:
- 优先读取最近的
tsconfig.json
或jsconfig.json
。 - 如果没有配置文件,就用 inferred project(推断项目),把打开的文件单独作为一个上下文。
项目引用 project references
在 tsconfig.json 使用 project references 时,tsserver 会:
解析所有引用的 tsconfig,为每个项目创建一个 ConfiguredProject。
建立项目依赖图,跨项目共享类型信息。
通过增量更新机制保持依赖关系的实时同步。
提供跨项目的补全、跳转、错误提示,而不进行真正的构建。
1. 例子目录结构
bash
/app/tsconfig.json
/core/tsconfig.json
/utils/tsconfig.json
/shared/tsconfig.json
2. 配置关系
app
依赖core
、utils
core
依赖utils
utils
依赖shared
json
// app/tsconfig.json
{
"compilerOptions": { "composite": true },
"references": [
{ "path": "../core" },
{ "path": "../utils" }
]
}
json
// core/tsconfig.json
{
"compilerOptions": { "composite": true },
"references": [
{ "path": "../utils" }
]
}
json
// utils/tsconfig.json
{
"compilerOptions": { "composite": true },
"references": [
{ "path": "../shared" }
]
}
json
// shared/tsconfig.json
{
"compilerOptions": { "composite": true }
}
3. 依赖图(tsserver 内存中的 Project Graph)
markdown
app
/ \
core utils
\ |
\ shared
\ /
4. tsserver 处理流程(增量更新)
-
初始化
- 打开
app
项目时,tsserver
发现它有references
,递归解析:app → core → utils → shared
。 - 为每个
tsconfig
建立一个ConfiguredProject
,形成项目图。
- 打开
-
类型查询
- 在
app
里写代码时,如果用到core
或utils
的类型,tsserver
会直接去对应项目的类型快照里查。 - 如果再间接引用到
shared
,也会一路查下去。
- 在
-
修改 shared
- 当你改动
shared
里的类型(例如type User = { name: string }
→type User = { name: string; age: number }
)。 tsserver
会标记shared
项目为 dirty。
- 当你改动
-
增量更新
utils
依赖shared
→ 重新检查utils
的类型。core
依赖utils
→ 重新检查core
的类型。app
依赖core
和utils
→ 重新检查app
的类型。
-
结果
- 最终在 VS Code 里,
app
中用到User
类型的地方会立刻提示 缺少age
属性。 - 全过程在内存完成,不需要执行
tsc -b
。
- 最终在 VS Code 里,
5. 总结图(影响传播链)
scss
shared (改动)
↓
utils (重新检查)
↓
core (重新检查)
↓
app (重新检查并提示错误)
✅ 一句话总结 : 在 Project References 模式下,tsserver
内部维护一张项目依赖图,当底层项目(如 shared
)类型变化时,会通过图逐层向上传递,保证顶层项目(如 app
)的智能提示和类型检查始终正确。(注:内容来源ChatGPT)
参考文章: