VS Code 越用越慢?别忘了定期审计过时插件
VS Code 用久以后,很容易积累一长串插件。
它们大多是在某个具体时刻安装的:缺少自动导入,于是装一个 Auto Import;希望自动补全标签,于是装 Auto Close Tag;想看 Mermaid、Git 提交图、TODO 列表,再分别装几个扩展。
问题是,VS Code 本身也在持续演进。过去需要插件提供的能力,几年后可能已经内置;以前只在特定文件中工作的扩展,后来可能变成每次打开 workspace 都会启动。插件列表没有变化,编辑器的运行环境却早已不同。
最近一次 VS Code 启动缓慢的排查,就遇到了这种情况。
一开始怀疑文件监听和缓存
项目打开慢时,最容易怀疑三个方向:
- 项目文件太多。
node_modules、dist等目录被错误监听。workspaceStorage或通用缓存积累过多。
检查后,这几个方向都没有明显异常:
- 项目大约有 7,300 个文件,不属于夸张规模。
node_modules、dist、日志和追踪目录已经配置监听排除。- 项目对应的
workspaceStorage只有约 5.9 MB。 - VS Code 日志中没有
ENOSPC、EMFILE或 watcher limit 错误。
真正异常的是 Extension Host。
code --status 一度显示当前窗口的 Extension Host 占用 100% CPU,日志也连续记录了无响应。VS Code 自动生成的性能采样把主要耗时指向:
steoates.autoimport@1.5.4一个自动导入插件为什么能拖慢整个编辑器
这个插件的工作方式很直接:打开 TypeScript 文件后,扫描 workspace 中的所有 TS/TSX 文件,找出可以导入的符号,再提供自动补全。
问题在于,它不是只处理当前文件。
插件激活时会读取全部 TS/TSX 文件,提取 export;随后还会再读取一遍,解析 import。文件发生变化时,它还可能再次执行项目级扫描。内部没有完善的并发限制、取消或 debounce,符号去重则依赖不断增长的数组做线性查找。
在一个接近 3,000 个 TS/TSX 文件的项目里,这意味着大量文件读取、正则解析和重复查找会集中回到 Extension Host 的 JavaScript 主线程。
Extension Host 又不是这个插件的独立进程。多个扩展共享它,一个插件长期占用主线程时,代码补全、Git 状态、格式化、其他语言服务乃至整个窗口响应都会一起受影响。
更关键的是,VS Code 已经内置了 TypeScript / JavaScript 自动导入。官方文档也明确说明,项目级 IntelliSense 包含 auto imports。继续保留这个旧插件,相当于用一套额外的全项目扫描,重复实现编辑器已经具备的能力。
这次清理了哪些插件
最终清理的不只是 Auto Import,还包括一批已经内置、功能重叠或对当前项目没有用途的扩展:
| 插件 | 清理原因 |
|---|---|
steoates.autoimport | 与内置 TS/JS 自动导入重复,并被性能采样定位为阻塞来源 |
bierner.markdown-mermaid | Mermaid 预览已在 VS Code 1.121 合入内置扩展,现有日志出现重复注册 |
formulahendry.auto-close-tag | 标签自动闭合大部分已由 VS Code 和语言服务提供 |
formulahendry.auto-rename-tag | HTML linked editing 与 TSX 标签重命名已有内置支持 |
christian-kohler.path-intellisense | VS Code 与 TypeScript 已有路径补全,并能理解 tsconfig paths |
gruntfuggly.todo-tree | 会扫描整个 workspace,性能采样中也出现过相关无响应 |
unifiedjs.vscode-mdx | 当前项目没有 MDX,却会被普通 TS/TSX 文件激活 |
xyc.vscode-mdx-preview | 当前项目不使用 MDX,扩展体积和收益不匹配 |
sanaajani.taskrunnercode | VS Code 已有内置 Tasks 与 npm Scripts,并且该插件全局激活 |
这里需要强调:这些插件不全是“坏插件”。
Todo Tree 对依赖 TODO 面板的人仍然有价值,MDX 插件对真正开发 MDX 的项目也很重要。问题不在插件存在,而在它是否仍然适合当前环境。
所谓“过时插件”,至少有四种:
- 功能已被编辑器内置。
- 与另一个扩展重复。
- 当前不再使用,却仍然全局激活。
- 工作方式会全量扫描 workspace,成本已经超过收益。
如何检查自己的插件
先看运行状态
在终端执行:
code --status重点观察:
extension-host是否长期高 CPU。file-watcher是否异常繁忙。- TypeScript Server 或其他语言服务器是否占用过高。
- 是否同时打开了太多大型 workspace。
再看 Extension Host 日志
macOS 上,VS Code 日志默认位于:
~/Library/Application Support/Code/logs/可以重点搜索:
Extension host is unresponsive
UNRESPONSIVE extension host
activation failed
ENOSPC
EMFILE
watcher如果日志已经明确给出某个扩展的性能归因,就优先验证这个扩展,而不是直接删除缓存。
定期查看完整插件列表
code --list-extensions --show-versions面对每个插件,可以问六个问题:
- 这个能力现在是否已经被 VS Code 内置?
- 是否安装了两个实现同一功能的插件?
- 我现在还开发对应的语言或框架吗?
- 它是否在所有 workspace 中启动?
- 它最近是否仍然维护和更新?
- 能否改成只在需要的 workspace 中启用?
用 A/B 验证代替盲目卸载
对可疑插件,先选择 Disable (Workspace),然后 Reload Window。
比较禁用前后的启动时间、Extension Host CPU 和内存。如果问题明显消失,再决定是否彻底卸载。候选很多时,还可以使用 VS Code 的 Extension Bisect,通过二分法缩小范围。
不要把清缓存当成第一反应
workspaceStorage 和通用缓存确实可能损坏,但清理它们不应该是第一步。
缓存清理会重置部分工作区状态,却不一定解决真正的高 CPU 插件。更稳妥的顺序是:
运行状态
-> Extension Host 日志
-> 文件监听配置
-> 插件 A/B 验证
-> 最后才是备份和清理缓存这样能避免把“插件每次都在重复做昂贵工作”误判为“一次性的缓存损坏”。
给插件维护一个固定节奏
插件性能问题往往不是安装当天出现的。
随着 VS Code 更新、语言服务增强、项目规模扩大和技术栈变化,原本合理的插件会逐渐变成重复能力或隐性成本。因此,插件也需要维护周期:
- 每月处理插件更新。
- 每季度审计一次完整插件列表。
- VS Code 大版本升级后,检查哪些第三方能力已经内置。
- 不再使用某种语言或框架时,移除对应工具链。
- 遇到启动变慢时,先检查 Extension Host,而不是凭感觉清缓存。
插件不是越多越好,也不是越少越好。
一个稳定的编辑器环境,需要让每个插件回答三个问题:它提供了什么不可替代的能力,它为什么需要在当前 workspace 启动,它带来的成本是否仍然值得。
定期更新插件很重要,定期删除已经不再需要的插件同样重要。编辑器性能往往不是突然坏掉的,而是在一次次“先装着,以后再说”中慢慢退化。
参考: