VS Code TypeScript 语言服务器频繁崩溃、CPU 常态占用的排查与解决

一、问题背景

最近在使用 VS Code 开发一个大型 Vue 项目时,发现 TypeScript 语言服务器(TSServer)持续占用 CPU,并且不断进行项目初始化。

VS Code 反复出现以下提示:

正在初始化“frontend/tsconfig.json”

同时还会收到警告:

在过去 5 分钟内,JS/TS 语言服务崩溃了 5 次。这可能是由以下其中一个扩展提供的插件引起的:Vue.volar。

项目本身采用 Monorepo 结构,包含多个 Vue 子项目以及大量 TypeScript 文件,使用了 Vue Official(Volar)扩展。

主要表现

  • VS Code 长时间处于 TypeScript 项目初始化状态。
  • TSServer 持续占用 CPU,影响编辑器使用体验。
  • JavaScript/TypeScript 语言服务频繁崩溃并自动重启。
  • VS Code 提示可能与 Vue.volar 扩展有关。
  • 重启 VS Code 后问题仍然出现。

经过排查,最终通过调整 TSServer 的最大堆内存限制解决了反复崩溃的问题。

二、问题排查

2.1 查看 TSServer 错误日志

打开 VS Code,按下 Ctrl + Shift + P,执行:

TypeScript: Open TS Server Log

也可以通过:

视图 → 输出 → TypeScript

查看语言服务相关信息。

排查过程中,发现以下错误:

2026-10-15 16:39:08.294 [error] TSServer exited.
Code: 134. Signal: null

其中:

  • TSServer exited:TypeScript 语言服务器异常退出。
  • Code: 134:进程异常终止,通常与 abort() 有关。
  • Signal: null:没有报告具体的终止信号。

退出码 134 并不直接等于内存溢出,但在 Node.js/V8 环境中,堆内存耗尽是常见诱因之一。

如果日志中还出现以下错误,则可以进一步确认内存问题:

FATAL ERROR: Reached heap limit
Allocation failed - JavaScript heap out of memory

或者:

FATAL ERROR: Ineffective mark-compacts near heap limit
Allocation failed - JavaScript heap out of memory

本次排查没有直接捕获到上述 V8 致命错误,但后续调整内存上限后的表现进一步支持了内存不足的判断。

2.2 分析 TypeScript 项目配置

项目根目录的 tsconfig.json 中,存在以下配置:

{
  "include": [
    "packages/**/*.ts",
    "packages/**/*.vue",
    "packages/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

这意味着 TypeScript 需要分析 packages 目录下大量的 TS、TSX 和 Vue 文件。

同时,项目中的各个 package 还存在相互依赖。

在 TSServer 日志中,可以观察到大量模块解析和文件监听记录:

FileWatcher:: Added:: WatchInfo
DirectoryWatcher:: Added:: WatchInfo
WatchType: Failed Lookup Locations

这些信息说明 TypeScript 正在进行大量模块解析,并对相关路径建立文件监听。

需要说明的是,Failed Lookup Locations 本身并不是错误,而是 TypeScript 模块解析机制中的正常行为。

不过,在大型 Monorepo 项目中,跨 package 依赖、庞大的类型声明和复杂的类型推导,都可能显著增加语言服务器的内存消耗。

三、解决方案:提高 TSServer 最大堆内存

3.1 修改 VS Code 工作区配置

  1. 按下 Ctrl + Shift + P。
  2. 搜索 Preferences: Open Workspace Settings (JSON)。
  3. 打开工作区设置文件。
  4. 添加以下配置并保存:
{
  "typescript.tsserver.maxTsServerMemory": 8192
}

其中,8192 表示 8192 MB,即 8 GB。

该配置用于调整 VS Code 启动 TypeScript 语言服务器时使用的 Node.js/V8 堆内存限制。

需要注意,这不是整个进程的总内存上限,也不代表启动后就会立即占用 8 GB。

3.2 重新启动 TypeScript 语言服务器

修改完成后,按下:

Ctrl + Shift + P

执行:

TypeScript: Restart TS Server

如果需要确保所有相关进程重新启动,也可以执行:

Developer: Reload Window

使工作区配置重新生效。

3.3 验证修改效果

本次排查中,将最大堆内存配置为 8192 MB 后:

  • TSServer 不再频繁崩溃。
  • VS Code 不再反复出现语言服务崩溃提示。
  • 项目初始化可以正常完成。
  • TSServer 内存占用约为 3.46 GB。
  • 初始化完成后,观察到 TSServer 的 CPU 占用降至 0%。

说明此前的内存限制很可能不足以支撑当前项目的完整分析。

对于大型 Vue/TypeScript Monorepo 项目,可以根据实际内存使用情况考虑调整:

配置值堆内存限制
30723 GB
40964 GB
61446 GB
81928 GB

需要注意,VS Code、Node.js 和 TypeScript 的版本可能影响实际默认堆内存限制,不能认为所有环境默认都严格为 3 GB。

建议先使用 4096 MB 或 6144 MB 进行测试。如果仍然出现堆内存不足,再适当提高。

本次项目最终使用 8192 MB,语言服务器运行恢复稳定。

四、查看 TSServer 内存占用

VS Code 内置了进程资源管理器,可以直接查看语言服务器的资源使用情况。

按下:

Ctrl + Shift + P

执行:

Developer: Open Process Explorer

在进程列表中,找到类似:

electron-nodejs (patch:tsserver.js; tsserver.js)

本次排查中观察到两个相关进程:

进程内存占用
TSServer 进程 1175 MB
TSServer 进程 23460 MB

VS Code 的 TypeScript 扩展可能启动多个语言服务器进程,分别承担不同的分析任务。

其中,占用较高的进程通常负责较为复杂的项目语义分析。

如果想进一步确认进程实际使用的启动参数,可以在 Windows PowerShell 中执行:

Get-CimInstance Win32_Process |
    Where-Object {
        $_.CommandLine -like "*tsserver.js*"
    } |
    Select-Object ProcessId, CommandLine |
    Format-List

检查输出中是否存在:

--max-old-space-size=8192

如果存在,说明相应 Node.js 进程已配置对应的 V8 Old Space 限制。

五、进一步优化:降低 TypeScript 项目分析开销

提高堆内存上限能够解决内存不足引发的崩溃,但并不意味着项目的 TypeScript 分析开销已经得到优化。

对于大型 Monorepo 项目,还可以从 tsconfig.json 入手。

5.1 减少不必要的文件扫描

例如:

{
  "compilerOptions": {
    "skipLibCheck": true,
    "checkJs": false
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue"
  ],
  "exclude": [
    "node_modules",
    "dist",
    "build",
    "coverage"
  ]
}

其中:

  • skipLibCheck:跳过声明文件的类型检查,减少部分类型检查开销。
  • checkJs: false:关闭 JavaScript 文件的类型错误检查。
  • include:限制直接纳入当前 TypeScript 工程的源码范围。
  • exclude:排除不需要作为根文件加载的目录。

注意,这只是示例配置,实际使用时应保留原项目已有的必要编译选项。

另外,exclude 并不能完全阻止通过 import 引用的文件被加载。

5.2 合理拆分 Monorepo 中的 TypeScript 工程

如果项目结构类似:

frontend/
├── packages/
│   ├── portal/
│   ├── admin/
│   ├── cloudpivot-form/
│   └── cloudpivot-portal-designer/
└── tsconfig.json

则可以考虑为各个 package 配置独立的 tsconfig.json,避免所有项目文件都被同一个 TypeScript 工程直接包含。

必要时,还可以结合 TypeScript Project References 管理项目间依赖。

不过,拆分工程需要结合实际的模块引用关系、构建工具和类型声明生成流程设计,不能简单地删除跨 package 引用。

5.3 其他 VS Code 配置

还可以根据项目情况选择性添加:

{
  "typescript.tsserver.maxTsServerMemory": 8192,
  "typescript.disableAutomaticTypeAcquisition": true,
  "files.watcherExclude": {
    "**/node_modules/**": true,
    "**/dist/**": true,
    "**/build/**": true
  }
}

其中,typescript.disableAutomaticTypeAcquisition 主要用于关闭自动获取类型定义的行为。

files.watcherExclude 则用于减少 VS Code 文件系统监听开销,并不等同于禁止 TypeScript 解析这些目录。

这些配置可以作为辅助优化手段,但无法替代对实际项目依赖和类型分析开销的排查。

六、总结

本次问题的核心表现是:

大型 Vue Monorepo 项目使 TypeScript 语言服务器消耗大量内存,在原有堆内存限制下频繁异常退出,进而造成不断初始化和 CPU 重复负载。

最终通过提高 TSServer 堆内存限制解决了问题。

关键配置只有一项:

{
  "typescript.tsserver.maxTsServerMemory": 8192
}

需要区分两个层面:

  • 提高堆内存上限:解决语言服务器因内存不足而崩溃的问题。
  • 优化 TypeScript 工程配置:减少不必要的文件扫描、模块解析和类型检查开销。

对于大型 Vue、React 或其他 TypeScript Monorepo 项目,当 VS Code 出现 TSServer 频繁崩溃、重复初始化、CPU 占用异常等现象时,可以优先检查进程内存和退出日志,再根据实际情况调整内存限制。

如果提高堆内存后语言服务器能够稳定完成初始化,并且空闲时 CPU 占用恢复正常,那么通常不需要急于进行大规模工程改造。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注