vscode插件调试必须通过extension development host实例运行,而非主编辑器窗口;type必须为extensionhost,runtimeexecutable指向vscode可执行文件,args需含--extensiondevelopmentpath=${workspacefolder},且outfiles须匹配编译后js路径。

VSCode 插件调试不是配好 launch.json 就能跑通的——它依赖正确的启动方式、正确的运行时上下文,以及对 extensionHost 和 renderer 进程的明确区分。
为什么直接 F5 启动插件会报错 “Cannot find module”
常见现象是:点击调试按钮后控制台报 Cannot find module './extension' 或 Extension 'xxx' is not activated。这不是路径写错了,而是 VSCode 没有以“扩展开发主机”模式加载你的代码。
根本原因在于:VSCode 插件必须运行在专用的 Extension Development Host 实例中(一个干净的、隔离的 VSCode 窗口),而不是你日常使用的主编辑器窗口。这个实例由 vscode-test 或 npm run test 启动,它会自动注入 package.json 中声明的 main 入口,并设置好 __dirname 和模块解析路径。
- 不要手动执行
node ./src/extension.js—— 这绕过了整个 VSCode 扩展生命周期 - 确保
package.json的main字段指向编译后的 JS 文件(如./out/extension.js),而不是 TS 源码 - 如果用 TypeScript,必须先运行
npm run compile(或启用watch);调试器不会自动编译 TS
如何配置 launch.json 调试 extensionHost 进程
VSCode 官方模板生成的 launch.json 通常只包含一个 Launch Extension 配置,但它隐含了关键参数:它本质是启动一个新 VSCode 实例,并把当前工作区作为 --extensionDevelopmentPath 传入。
你需要确认以下三点:
-
type必须为extensionHost(不是node或chrome) -
request必须为launch,且runtimeExecutable应指向本地 VSCode 可执行文件(Windows 是code.cmd,macOS 是Visual Studio Code.app/Contents/MacOS/Electron) -
args中必须包含--extensionDevelopmentPath=${workspaceFolder},否则插件根本不会被加载
示例最小可用配置:
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": ["${workspaceFolder}/out/**/*.js"],
"preLaunchTask": "npm: compile"
}
]
}
调试 renderer 进程中的 Webview 或 WebViewPanel
如果你的插件用了 WebviewPanel、WebView 或内嵌 HTML 页面,它的 JS 是运行在独立的 renderer 进程里的,和 extensionHost 完全隔离。断点打在 extension.ts 里不会触发,打在 webview 的 JS 里也不会停住——除非你额外打开 DevTools。
正确做法是:在插件代码中调用 webviewPanel.webview.onDidReceiveMessage 后,右键 webview 区域 → “Inspect Context”(或按 Ctrl+Shift+I),打开 Chromium DevTools。这时你才能在 Sources 面板里找到 vscode-webview:// 协议下的脚本,设断点、查 console、看网络请求。
- Webview 的 HTML/CSS/JS 必须通过
webview.html或webview.cspSource正确注入,不能用本地file://路径(会被 CSP 拦截) - 调试前务必检查 DevTools Console 是否有
Refused to load resource报错,大概率是资源路径没用webview.asWebviewUri转义 - 不要在 webview 中直接
importnode 模块——renderer 进程默认禁用 Node.js 集成(除非显式开启enableScripts和localResourceRoots)
测试时 extensionContext.extensionPath 为什么是空的
这个值为空,往往发生在你用 vscode-test 做自动化测试时,但没传入正确的 --extensionDevelopmentPath 参数,或者测试脚本本身没等插件激活就调用了 context.extensionPath。
真实场景下:extensionContext.extensionPath 只在 activate() 函数执行期间及之后才有效。如果你在 activate 外部(比如模块顶层)访问它,必然为 undefined。
- 所有依赖
context的逻辑,必须包裹在activate(context)内部,或通过闭包传递出去 - 单元测试中若需模拟 context,应使用
vscode.TestExtensionContext(来自@types/vscode)而非手动生成空对象 - 调试时可在
activate开头加console.log(context.extensionPath),确认路径是否指向你期望的out/或dist/目录
插件调试最易被忽略的一点:你看到的“调试窗口”其实是两个进程的叠加——extensionHost 负责命令注册、状态管理,renderer 负责 UI 渲染。它们日志分开、断点独立、崩溃互不影响。不区分这两者,90% 的“断点不触发”问题都无解。











