热重载失效主因是调试配置错误或文件监听失效;需确认 launch.json 中 type 为 extensionhost、runtimeexecutable 指向 vscode,启用 tsconfig watchoptions,排除 node_modules 监听,并确保状态在 activate/deactivate 中正确管理。

热重载失效时,vscode-extension-dev 启动脚本没起作用
VSCode 插件开发中热重载(Hot Reload)不是开箱即用的——它依赖 vscode-extension-dev 脚本启动调试会话,而不是直接运行 npm run watch 或手动 F5。如果改完代码没反应,第一件事是确认你当前调试配置的 type 是 extensionHost,且 request 为 launch,同时 runtimeExecutable 指向的是 VSCode 可执行文件(非 Node.js),否则热重载根本不会注入。
常见错误现象:Debugger attached. 日志出现,但修改 extension.ts 后保存,插件行为无变化,也无 reload 提示。
- 检查
.vscode/launch.json中是否包含"recompileOnSave": true(这个字段无效,VSCode 不识别) - 确保
out目录由 TypeScript 编译生成(不是src直接运行),且main入口在package.json中指向./out/extension.js - 禁用所有非必要插件(尤其是其他热重载类插件),避免调试通道被劫持
extension.js 修改后不触发重载,但 webpack 构建的插件可以
原生 TS 插件热重载只监听 out/**/* 下的 JS 文件变更,并通过 VSCode 内部机制触发 extension host 重启模块。如果你用 tsc -w 编译,它默认不发出文件系统事件(尤其在某些 WSL 或 Docker 场景下),导致 VSCode 无法感知变更。
解决方式不是换构建工具,而是让编译器“说真话”:
- 在
tsconfig.json中启用"watchOptions": { "watchFile": "useFsEvents", "fallbackPolling": "dynamicPriority" } - 或更稳妥:改用
npm run watch调用tsc --watch --preserveWatchOutput,并确保终端输出含Found 0 errors. Watching for file changes. - 避免把
out目录挂载到网络盘或加密卷——FS 事件可能被静默丢弃
热重载后状态丢失,activate 重复执行但全局变量未重置
热重载本质是卸载旧模块 + 加载新模块,但 Node.js 的模块缓存(require.cache)不会自动清空,尤其当你在 extension.ts 外部 import 了带副作用的模块(比如初始化日志、注册全局单例),这些逻辑会在每次 activate 时叠加执行。
这不是 bug,是设计使然。要控制状态生命周期:
- 把插件主逻辑封装进类实例中,在
deactivate里显式销毁(如清除setTimeout、注销Disposable) - 避免在模块顶层写执行语句;把初始化移到
activate函数内,或用let instance: MyService | undefined+ 懒加载模式 - 调试时注意:VSCode 不会调用
deactivate直到你手动停掉调试会话或关闭窗口——热重载期间该函数实际未运行
Windows 上热重载卡住,EMFILE: too many open files
这是 Node.js 在 Windows 下 watch 模式默认打开太多文件句柄导致的,尤其当工作区包含 node_modules 或大型资源目录时。VSCode 的扩展主机进程本身也会递归监听子目录,叠加后极易突破系统限制。
最轻量解法是收缩监听范围:
- 在项目根目录加
.vscode/settings.json,写入:"files.watcherExclude": { "**/node_modules/**": true, "**/out/**": true, "**/dist/**": true } - 在
tsconfig.json的compilerOptions中添加"exclude": ["node_modules", "out"] - 不要在
launch.json中设置"sourceMaps": true同时又开启webpacksourcemap——双重映射会显著拖慢 reload 响应
热重载真正可靠的前提,是你清楚哪些文件变更会被捕获、哪些状态必须手动管理、以及你的开发环境对 FS 事件的真实支持程度。一旦遇到“改了没反应”,先看终端有没有 Extension Host restarted 日志,再查编译输出和文件监听路径——不是所有保存都等于重载。











