1. 别被报错吓到:先认清这次崩溃的本质
今天早上打开一个 Vue 3 + TypeScript 项目,还没来得及看类型报错,VS Code 右下角就弹出一段看起来像事故现场的提示:JS/TS 语言服务已立即崩溃 5 次。不会重新启动该服务。这可能是由以下其中一个扩展提供的插件引起的: Vue.volar。请在针对 VS Code 提交问题之前尝试禁用这些扩展。
第一次遇到这个提示的人,大概率会愣一下:我什么都没动,怎么就把编辑器搞崩了?其实这个提示虽然长得吓人,但问题范围非常明确。它不是在说你的电脑坏了,也不是说项目代码里有致命错误,而是 VS Code 的 TypeScript 语言服务进程反复启动、反复闪退,最后系统放弃治疗,决定不再重启了。
这时候最怕的就是病急乱投医。有人直接卸载 Volar,有人把设置文件清了一遍,还有人干脆换了编辑器。实际上,只要理解了这个报错的来龙去脉,绝大多数情况下都能在十分钟内解决,而且不用牺牲 Vue 的智能提示。
1.1 报错里的“JS/TS 语言服务”到底是什么
VS Code 里你看到的“代码自动补全、跳转定义、类型错误红线、重命名符号”,背后靠的并不是 VS Code 主进程,而是一个独立的 Node.js 后台服务,官方叫 TypeScript Server,简称 tsserver。这个进程负责加载你的项目、分析 tsconfig、维护程序符号表和类型信息,再把结果以请求响应的形式反馈给编辑器。
你可以把它理解成一个图书馆管理员。你每次想查一本书、想知道某个类型定义在哪,都由这个管理员去找。管理员累了、挂了、或者踩到香蕉皮摔了,VS Code 的界面上就会显示“语言服务崩溃”。
“已立即崩溃 5 次”的意思是:VS Code 曾经尝试重新拉起这个服务,但每次拉起后在极短时间内又崩了,连续失败五次,系统认为再试也没意义,于是停手。这个“5 次”不是固定值,但表达的意思都一样:崩溃不是偶发,而是每次启动都会触发。
1.2 它崩溃之后,你损失了什么
tsserver 崩溃后,你失去的不是编辑能力,而是“智能”能力。文件还能正常输入保存,但代码提示、悬停类型、自动导入、错误诊断这些功能会全部失灵,或者变得非常迟钝。
最直观的体验就是:你敲出一个对象属性,想看看有什么可选字段,发现提示框不出来了;你写错了一个类型,红色波浪线也不出现了。这时候如果还在往下写代码,基本等于盲写,风险很高。
所以看到这个报错后的第一优先级不是继续肝代码,而是先恢复语言服务。恢复方式不复杂,关键是先别慌,按顺序处理即可。
1.3 为什么弹窗专门点 Volar 的名
报错文案里明确提到了 Vue.volar,这是因为 VS Code 有一套插件机制,允许扩展向 tsserver 注入“TS 插件”。Volar 正是通过这种插件机制来识别.vue文件里的<script>块、模板表达式、以及组件 Props 类型推导的。
如果 Volar 注入的插件在处理某个文件时抛出了致命异常,tsserver 进程就会退出。VS Code 捕获到这个退出事件后,会根据是什么插件造成的进程崩溃,给出这样的提示。所以弹窗点 Volar 的名,并不等于 Volar 百分百是恶意元凶,但基本上可以确定问题发生在 Volar 和语言服务的协同环节上。
2. 理解 Volar 和 tsserver 之间的关系,比盲目禁用更有用
很多人在这个问题上吃亏,是因为把“扩展崩溃”和“扩展是垃圾”画了等号。Volar 不是普通的语法高亮插件,它的工作方式比想象中复杂得多。
2.1 Volar 不是“普通高亮插件”
Volar 的官方名是 Vue Language Features,核心能力是给 Vue SFC(单文件组件)提供完整的语言服务。它不仅仅做高亮,而是要把一个.vue文件拆开、解析、虚拟化成 tsserver 可以理解的 TS 文件,再把模板、脚本、样式之间的关系梳理好。
比如你在<script setup lang="ts">里定义了一个defineProps,Volar 要负责把 Props 的类型推导到模板表达式中,让你在<template>里写{{ item.name }}时也能有跳转和类型提示。这种“跨区块的类型推导”本质上是重建了一个虚拟 TS 项目,再交给 tsserver 去分析。
随着 Vue 3 的应用越来越复杂,Volar 每次解析的文件数量、内存占用、虚拟文件更新频率都会成倍增加。这也是为什么项目一旦变大,这个报错出现的概率就明显上升。
2.2 “插件”是压垮 tsserver 的最后一根稻草
tsserver 本身是一个长期运行的 Node.js 进程,内部有一套插件 API。第三方扩展可以注册插件,告诉 tsserver“遇到某种文件时先让我来处理”。Volar 注册后,tsserver 在处理.vue文件时会调用 Volar 提供的代码。
这里的问题在于,tsserver 对插件的错误容忍度并不高。插件如果只是返回一个错误结果,也许还能兜住;但如果是未捕获异常、内存溢出、或者接口返回了不符合预期的数据结构,就可能直接带崩整个进程。VS Code 重试五次都没能救回来,说明这个错误是稳定复现的,也就是说某个文件或某个状态每次都会触发它。
2.3 新旧 Volar 扩展混装,是常见的隐藏炸弹
Volar 的历史版本迭代里有一个很惹人烦的时期:早期用 Vue 3 + TS 时,经常需要同时安装两个扩展,一个是Vue.volar,另一个是Vue.vscode-typescript-vue-plugin。后者专门用来让 tsserver 识别.vue文件里的 TS 内容。
后来 Volar 更新到接管模式之后,官方其实已经不再推荐同时装这两个扩展,但在很多人的 VS Code 里,旧扩展还残留着。两个扩展同时作用于同一个 tsserver 进程,就很容易出现重复注册、版本不匹配、插件冲突的连锁反应。所以排查这个崩溃时,我通常先看一眼插件列表里有没有“Vue”相关的重复项。
3. 先让编辑器恢复能用:三步紧急处理
不管最终原因是什么,第一步都是先让 VS Code 从“反复崩溃”的状态里出来。这个阶段的目标不是根治,而是先恢复一个可以正常写代码的环境。
3.1 禁用 Volar 并重载窗口
在左侧扩展面板搜索Vue,找到Vue Language Features (Volar),点击禁用,然后通过命令面板执行Developer: Reload Window重载窗口。
这一步看起来简单,但很多人做完没效果,原因是忘了重载。禁用扩展后,VS Code 并不会立刻停掉已经崩溃过的 tsserver 进程,必须重载整个窗口才会重启语言服务。重载后如果右下角不再弹崩溃提示,哪怕只是暂时不弹,也说明问题确实和 Volar 相关。
此时你会失去 Vue 文件的部分语法高亮和类型推导,但至少 JS/TS 文件内的编辑体验能恢复,代码不至于完全没法写。这是一个典型的“先止损,再定位”的思路。
3.2 清掉 Volar 的本地缓存状态
禁用扩展能解决的是“当前加载 Volar 插件导致崩溃”的情况,但很多时候崩溃的根源不在插件本身,而在于 Volar 保存在工作区存储里的状态数据已经损坏。
VS Code 为每个工作区单独维护一个 storage 文件夹,扩展会把本地状态写到里面。文件路径在不同系统上不一样:
- Windows:
%APPDATA%\Code\User\workspaceStorage - macOS:
~/Library/Application Support/Code/User/workspaceStorage - Linux:
~/.config/Code/User/workspaceStorage
进入这个目录后,你会看到一堆以 hash 命名的文件夹,每个文件夹对应一个 workspace。根据文件夹里的workspace.json可以判断是哪个项目,或者直接按修改时间排序,找最近频繁变动的那个。关掉 VS Code 后,把对应文件夹里的内容备份并清空,再重新打开项目。
这个方法能解决大量“禁用扩展后看似恢复正常,但重新启用 Volar 后又疯崩”的情况。我自己的经验是,清完 workspaceStorage 后,Volar 的虚拟文件缓存、文档状态、诊断状态都会被重置,很多莫名其妙的偶发崩溃都能被摁住。
3.3 检查有没有残留的旧版 Vue 插件
在终端执行:
code --list-extensions | grep -i vueWindows 下如果没有 grep,可以用 findstr:
code --list-extensions | findstr /i vue看到Vue.volar之外还出现类似Vue.vscode-typescript-vue-plugin的扩展,就把它卸载掉。旧版插件在当前 Volar 版本下已经没有必要保留,留着只会增加 tsserver 的负担。
如果你不确定哪个扩展该留,最简单粗暴的做法是把带 Vue 字样的扩展全部禁用,然后逐个启用。先只启用最新的Vue.volar,用半天项目,不崩了再考虑加别的扩展。
4. 为什么它反复崩?常见根源和判断方法
紧急恢复只是把火扑灭,如果不找出火源,下次打开项目大概率还会继续弹这个框。下面这些才是真正导致“JS/TS 语言服务反复崩溃”的常见根源。
4.1 版本错位:Volar、VS Code、TypeScript 三者对不上
Volar 依赖 tsserver 的插件 API 工作,而每个版本的 TypeScript 都有可能在插件接口上做调整。如果你项目里用的 TypeScript 版本和 Volar 官方支持的版本跨度太大,就可能出现插件接口调用异常,直接导致 tsserver 崩溃。
VS Code 自带的 TypeScript 版本通常是某个固定版本,比如 5.x 的某一版。如果你的项目通过 npm 安装的 typescript 是一个更老或更特别的 RC 版本,Volar 可能无法兼容。这时候 VS Code 右下角不一定有明确提示,只会表现为“偶尔崩、反复崩”。
在排查时,先查三个版本:
- VS Code 版本:
Help -> About - Volar 扩展版本:扩展面板中查找
- 项目 TypeScript 版本:在项目根目录执行
npx tsc --version
三个版本不要拉得太大。如果项目 TypeScript 版本很老,比如 4.x,而 Volar 已经是最新版本,两者可能已经不再兼容。反过来,Volar 旧版本遇上 TypeScript 5.5 这种大版本,也可能出问题。
4.2 接管模式没开启,导致两份 TS 服务互相挤兑
Volar 有两种工作方式:一种是以“插件”的形式寄生在 VS Code 内置 tsserver 里,另一种是开启接管模式,由 Volar 自己接管整个 TS 语言服务。
默认情况下,Volar 可能会走插件模式,也就是说每个.ts、.js、.vue文件的处理都要经过内置 tsserver,然后再回调给 Volar。此时如果 Volar 的处理逻辑和内置 tsserver 的版本逻辑有冲突,就会崩。
开启接管模式的方法不复杂:在扩展面板搜索@builtin TypeScript and JavaScript Language Features,把这个内置扩展禁用,然后重载窗口。禁用后,Volar 会检测到内置 TS 服务不可用,自动切换为接管模式,自己承担所有 TS/JS 语言服务职责。
我自己在多个项目里测试下来,接管模式比插件模式稳定得多。一方面是少了内置 tsserver 和 Volar 之间的来回转调,另一方面是不会出现两套服务同时监听文件变动的资源竞争。如果你一直遇到这个崩溃,我强烈建议先试试接管模式。
4.3 项目文件过重,内存把 tsserver 顶爆
Vue 3 项目结构一大,tsserver 的内存占用会非常夸张。尤其是 monorepo 或包含大量node_modules类型声明的项目,每次启动 tsserver 都要建立模块解析缓存、读 tsconfig、扫描 import。Volar 还要额外维护一份 Vue 虚拟文件树,内存占用直接翻倍。
如果你的电脑内存本来就紧张,加上杀毒软件、浏览器、编辑器的其他进程,tsserver 很容易在达到某个内存阈值后崩溃。此时的现象通常不是一启动就崩,而是用着用着提示语言服务已停止。在任务管理器里,你大概率会看到node进程占用了几个 GB 的内存。
这种情况不能只靠“禁用 Volar”解决,要给 tsserver 做减法。常见的思路是把项目目录下的dist、node_modules、.git等目录从文件监听和搜索范围里排除,减轻 tsserver 的负担。
4.4 杀毒软件或系统环境把 node 进程搞死
这个原因很少有人想到,但确实存在。某些安全软件会对新启动的进程做行为扫描,如果 tsserver 在短时间内频繁打开大量文件、建立网络连接或者写缓存,就可能被安全软件判定为异常行为,直接把进程杀掉。
判断方法也很简单:关掉安全软件的实时防护,重载 VS Code,用一段时间看还崩不崩。不过关防护不是长久之计,如果确认是这个原因,建议把 VS Code 的目录、项目缓存目录加入信任白名单,而不是长期关闭防护。
5. 根治:让 Volar 稳定工作的配置方案
解决了眼前崩溃之后,重点就是怎么让 Volar 安安稳稳地长期工作。下面的配置和方法都是我在实际项目里验证过比较有效的,可以直接照抄。
5.1 把 Volar 升到最新,并开启接管模式
打开扩展面板,搜索 Vue,确保当前安装的是官方最新版本。如果已有旧版本,卸载后重新安装,然后重启 VS Code。
接着执行以下操作:
- 命令面板输入
Extensions: Show Built-in Extensions - 找到
TypeScript and JavaScript Language Features - 点击禁用
- 重载窗口
重载后打开一个.vue文件,确认代码提示和类型诊断正常。如果此时状态栏能显示出 Vue 相关的语言服务标识,就说明接管模式已经生效。
需要提醒的是,接管模式会让 Volar 同时负责.ts和.js文件的处理,这对 Volar 本身的要求更高。如果某个项目的.ts文件逻辑非常复杂,反而可能放大 Volar 的崩溃概率。这种情况下,可以回到插件模式,但必须保证 Volar 和 TypeScript 版本配套。
5.2 在项目里锁定 TypeScript 版本
Volar 最好使用项目本地的 TypeScript 版本,而不是 VS Code 内置的版本。在项目根目录打开.vscode/settings.json,添加:
{ "typescript.tsdk": "node_modules/typescript/lib" }然后命令面板执行TypeScript: Select TypeScript Version...,选择Use Workspace Version。
这样设置的好处是,项目里面的 Volar 与 tsc 使用的是同一套类型系统,不会出现“编辑器里没问题、命令行里报错一堆”的割裂感。如果本地 typescript 版本不对,直接升级或降级到项目需要的位置,也能规避很多隐性问题。
需要注意,如果项目用的包管理器是 pnpm,node_modules/typescript可能是一个指向全局 store 的符号链接,理论上不影响读取,但偶尔会让 Volar 解析不了真实路径。遇到这种问题,把typescript显式安装到项目的devDependencies里会更可靠。
5.3 给 tsserver 减负:文件监控与搜索排除
项目文件越多,tsserver 启动和增量更新就越吃力。以下配置能显著降低崩溃概率,尤其是大型项目:
{ "files.watcherExclude": { "**/.git/objects/**": true, "**/node_modules/**": true, "**/dist/**": true, "**/coverage/**": true }, "search.exclude": { "**/node_modules": true, "**/dist": true, "**/coverage": true }, "typescript.tsserver.experimental.enableProjectDiagnostics": false }files.watcherExclude控制的是 VS Code 与 tsserver 的文件监听范围,排除不参与源代码构建的目录可以避免大量无意义事件触发类型推导。search.exclude则减少搜索时扫描的文件量。
最后一个enableProjectDiagnostics是控制 tsserver 是否在启动时对整个项目做全量诊断的选项,默认关闭。如果你发现打开项目后磁盘 IO 和 CPU 都会飙升,再检查一下有没有被某个插件重新打开,比如 Volar 的诊断或 ESLint 的全量校验。把不必要的东西关掉,抢救回来的内存可能很可观。
5.4 如果最新版还是崩,用稳定版 Volar 回退
有些版本在某次迭代里会引入回退,最新的不一定最稳。如果你更新到最新 Volar 后反而频繁出现这个报错,可以尝试回滚到前一个稳定版本。
在扩展面板里点击 Volar 的“安装其他版本”,选择一个你之前用着没问题的版本,然后重载窗口。如果没有明显的版本记忆,就去 GitHub Release 页面看是否有用户反馈类似问题,照着大家的反馈选一个相对稳的版本。
另外,如果尝试了这些仍不稳定,可以把类型检查独立出来,在命令行里使用vue-tsc --noEmit做完整类型检查。虽然这会损失一部分编辑器内的即时报错,但至少不会影响开发流程。用命令行辅佐编辑器,是处理语言服务反复崩溃的保底策略。
5.5 用 Extension Bisect 揪出元凶
如果上面所有配置都试了,崩溃还偶尔出现,那就要怀疑是不是有其他扩展和 Volar 产生了冲突。VS Code 自带一个二分定位工具,命令叫Developer: Extension Bisect。
它会通过开启一半扩展、禁用另一半扩展的方式,快速帮你定位到底哪个扩展和崩溃相关。整个过程是交互式的,它会在每次重载后问你“现在还能复现吗”,你只需要根据实际情况回答就行。大部分情况下,几分钟就能锁定到具体的扩展组合。
我自己遇到过最典型的组合是 Volar 配合某个老旧的自动导入扩展时,两个扩展同时对 import 语句做处理,导致 tsserver 在处理自动导入时崩溃。这个组合不是谁“坏”,而是功能重叠后引发了资源竞争。
6. 自己动手看日志与提交 Issue 的正确姿势
如果所有常规方法都用完了,问题仍然存在,那就该认真看日志,甚至给官方提 Issue。但提 Issue 不是把报错截图丢过去就行,好的 Issue 应该能让维护者快速定位问题。
6.1 在 VS Code 里快速抓崩溃线索
VS Code 的“输出”面板是第一个要看的地方。点击菜单栏的查看 -> 输出,在下拉框里选择TypeScript,这里能看到 tsserver 的启动日志、错误堆栈和崩溃原因。
如果下拉框里有Vue Language Server或者带 Vue 字样的日志源,也切换到那个源看看。每次“语言服务崩溃”的提示出现后,日志末尾通常会有Error: ...或者一段调用栈,那就是最直接的线索。
另一个有用的入口是命令面板执行Developer: Open Logs Folder,它会打开 VS Code 自己的日志目录,包括窗口运行日志、扩展宿主日志、共享进程日志。里面会有更详细的进程退出码,比如 SIGKILL、OOM、unknown error 等。
命令行下也可以用系统工具看 tsserver 的内存状况。比如 Windows 上执行:
tasklist | findstr node看到多个 node 进程后,要看哪一个是 tsserver,通常路径里带typescript或占用内存最大的就是它。如果内存接近 3GB 且崩溃前持续增长,基本可以断定是内存问题。
6.2 提交 Issue 前该准备的五样东西
按官方要求,遇到这类问题先禁用扩展再提 Issue,这本身就是一种筛选方式。如果禁用扩展后问题消失,那问题大概率与扩展相关,官方需要的是扩展的具体信息。
一个有效的 Issue 至少需要包含:
- VS Code 版本号
- Volar 扩展版本号
- 项目的 TypeScript 版本(
npx tsc --version输出) - 操作系统版本
- 输出面板中 TypeScript / Vue 日志的完整内容
- 最小复现步骤或最小项目仓库
很多人提 Issue 只贴一句“我的语言服务崩了”,这等于让维护者凭空猜。但如果你能把上面这些信息整理好,维护者基本一眼就能定位方向,回复速度也会快得多。
6.3 常见问题速查表
为了方便直接对照,我整理了一个速查表:
| 现象 | 大概率原因 | 推荐操作 |
|---|---|---|
| 弹窗频繁出现,禁用 Volar 后消失 | Volar 与 tsserver 插件机制冲突 | 更新 Volar,开启接管模式,卸载旧版 Vue 插件 |
| 禁用 Volar 后依然崩 | workspaceStorage 损坏 / 其他扩展冲突 | 清 workspaceStorage,用 Extension Bisect 定位 |
| 项目文件多,用着用着崩 | tsserver 内存压力过大 | 排除 node_modules、dist 等目录,减少监听范围 |
| 打开特定 .vue 文件才崩 | Vue SFC 解析异常,Volar 虚拟文件出错 | 看 Vue Language Server 日志,尝试回退 Volar 版本 |
| 升级 Volar 后开始崩 | 新版本存在回归 | 回退到上一个稳定版 |
| 开启接管模式后崩 | Volar 自身处理 TS/JS 逻辑时的 bug | 回到插件模式,或者改用 vue-tsc 做类型检查兜底 |
7. 最后再说几个我踩过的坑
先说一个很反直觉的事:Volar 不是越新越好。我曾在一次项目里连续遇到三四个版本都崩,最后发现是某个新版本里对defineModel的解析逻辑有 bug,回退一个版本立刻安静了。如果你不是必须要用最新特性,看到“版本更新可用”先别急着点,等一两周再看社区反馈。
还有一个容易踩的坑是,清完了 workspaceStorage 后,有些人会把整个.vscode目录也当成缓存删掉。这个目录里保存的是项目级别的配置,删了虽然不影响代码,但会把调试配置、扩展推荐、settings.json 都弄没,得不偿失。只需要清理workspaceStorage下对应的 hash 文件夹,不要扩大战果。
个人体会是,这类 JS/TS 语言服务崩溃,有八成以上能从“版本组合”这个维度解决问题。Volar 最新版 + 项目自带 TypeScript + 接管模式,能让绝大多数 Vue 3 项目稳定运行。剩下两成才是缓存损坏、扩展冲突和内存压力,这些也有对应的排查手段,不需要直接放弃 Volar 换编辑器。
如果你连禁用扩展都来不及,可以在终端用code --disable-extensions .这种方式临时打开项目,先把当前代码改完保存,再回来认真处理。它等于是给 VS Code 开了一个“纯净模式”,比在编辑器和弹窗之间反复打架舒服得多。JS/TS 语言服务崩溃不可怕,可怕的是反复用同一个方法瞎试却不看日志。冷静下来先救火、再定位、后根治,这个问题就只是开发路上的一小段插曲而已。