VSCode 保存卡顿大概率是代码复杂度插件与Prettier/ESLint在onSave阶段争抢资源、触发隐式循环所致;其默认全量AST重解析且无缓存,大文件下直接阻塞主线程。

VSCode 保存卡顿如果发生在启用代码复杂度分析类插件(如 spmeesseman.vscode-code-metrics、ckolkman.vscode-postcss 或自定义 ESLint + complexity rules)后,大概率不是“插件没跑”,而是它和 Prettier/ESLint/tsserver 在 onSave 阶段抢资源、互相触发,形成隐式循环。
为什么代码复杂度插件一开就卡保存?
这类插件通常监听 onSave 或 onType,并在保存时执行 AST 解析、圈复杂度计算、报告生成等 CPU 密集操作。问题不在于它慢,而在于它没排队——和 ESLint 的 eslint.codeAction.onSave.fixAll、Prettier 的 editor.formatOnSave 同时注册了同一个事件钩子。
- 你按 Ctrl+S → 所有插件同时启动:ESLint 扫一遍、Prettier 格式化一遍、复杂度插件再扫一遍 AST
- 若格式化后代码变更(比如缩进调整),ESLint 可能再次触发(尤其开了
eslint.format.enable),形成「保存 → 格式化 → 校验 → 再格式化」的死链 - AST 解析本身不缓存,每次都是全量重解析,大文件(>1000 行 TS/JS)直接卡主线程 300–800ms
如何快速确认是复杂度插件在作祟?
别猜,用 VSCode 自带工具三步定位:
- 终端执行
code --disable-extensions,打开同一文件,保存测试 —— 若秒响应,问题必在扩展 - 重启带插件的 VSCode,按 Ctrl+Shift+P → 输入并运行
Developer: Show Running Extensions,重点看:
•Activation Time (ms)是否超 800(说明它启动就占线程)
•Status是否长期卡在Activating或空白(加载失败但没报错) - 再按 Ctrl+Shift+P → 运行
Developer: Open Process Explorer,展开extensionHost,找 RSS > 400MB 或 CPU 持续 >30% 的插件名 —— 复杂度类插件常在此列
禁用前先调配置,避免误杀刚需功能
很多复杂度插件默认开启实时扫描或全项目分析,其实你只需要「保存时检查当前文件」就够了:
- 关掉全局监听:
"code-metrics.enabled": false(停用整个插件)
或更精细地:"code-metrics.runOnSave": true+"code-metrics.runOnType": false - 限制分析范围(对
eslint-plugin-complexity类规则):
在.eslintrc.js中显式指定只检查src/**/*.{js,ts},避免遍历node_modules或dist - 强制解耦流程:把复杂度检查从
onSave移到命令触发,比如删掉自动配置,改用快捷键Ctrl+Shift+P → Code Metrics: Analyze Current File
和 ESLint/Prettier 共存的最小安全配置
三者共存不卡的前提是「各干各的,不互相喊话」:
- 只留一个格式化入口:
"editor.formatOnSave": true+"editor.defaultFormatter": "esbenp.prettier-vscode"
同时关掉:"eslint.format.enable": false和"prettier.eslintIntegration": false - ESLint 只做校验:
"eslint.codeAction.onSave.mode": "all"(仅提示,不自动修)"eslint.validate": ["javascript", "typescript"](删掉javascriptreact等冗余项) - 复杂度规则必须收敛到 ESLint 里统一管理,而不是另起一个插件进程 —— 用
eslint-plugin-complexity替代独立插件,靠eslint主进程调度,天然排队
真正容易被忽略的点:复杂度插件往往没有「缓存 AST」机制,每次保存都重解析。哪怕你只改了一个分号,它也得把整棵树再过一遍。这不是 bug,是设计如此 —— 所以它从来就不该在 onSave 里默认启用。


















