vscode插件的运行时依赖必须本地安装并打包进.vsix,所有require/import的npm包须列在dependencies中,由vsce package一并包含;漏装会导致“cannot find module”错误,extensiondependencies仅声明插件协同关系,不解决模块加载问题。

VSCode插件的 dependencies 必须本地安装并打包进 .vsix
VSCode插件运行时不联网拉取 dependencies,所有运行时依赖必须在打包前通过 npm install 安装到本地 node_modules 中,并由 vsce package 一并塞进最终的 .vsix 文件里。漏掉这一步,插件加载时就会报 Cannot find module 'xxx'。
常见错误现象:
- 本地调试正常,但发布后功能失效(比如
axios调用报错) -
vsce package后生成的.vsix解压发现node_modules为空或缺失关键包 - 误把工具库写进
devDependencies,结果运行时找不到
实操建议:
- 检查
package.json:所有插件代码里require()或import到的第三方包,必须出现在dependencies字段中 - 执行
npm install后,用npm ls xxx验证包是否真实安装且版本可解析 - 打包前手动删掉
node_modules再重装一次,避免缓存导致的“看似存在实则损坏”
extensionDependencies 是软依赖,不解决运行时模块缺失
extensionDependencies 声明的是“我这个插件需要另一个 VSCode 插件同时启用”,比如你的插件要调用 ms-python.python 提供的语言服务器能力。它只影响安装流程提示,**不会帮你加载任何 JavaScript 模块**。
容易混淆的点:
- 以为写了
"extensionDependencies": ["ms-vscode.cpptools"]就能直接require("vscode-cpptools")—— 实际上不行,那是另一个插件的私有代码,你无法 import - 把本该放在
dependencies的库(如lodash)错放到extensionDependencies,导致运行时报错
正确做法:
-
extensionDependencies只用于声明对其他 VSCode 扩展的**功能协同依赖**,例如“需配合 Prettier 插件格式化代码” - 若需复用其他插件暴露的 API,必须确认对方明确提供了
exports机制(极少见),否则应自行实现或引入对应 npm 包
多层嵌套依赖易引发版本冲突,必须锁定
虽然每个插件有独立 node_modules,但若多个插件都依赖同一底层库(如 glob、minimatch)的不同大版本,且共享进程(如主 UI 进程),就可能因全局状态污染出问题——比如一个插件调用 glob.sync() 改变了内部正则缓存,另一个插件接着调用就返回异常结果。
典型症状:
- 单个插件测试正常,但与其他插件共存时出现不可复现的崩溃或逻辑错乱
- 错误堆栈指向第三方库内部,但你的代码没动过那部分
应对策略:
- 在
package.json中用精确版本号(如"lodash": "4.17.21"),禁用^和~ - CI 流程中加入
npm ls --depth=0检查顶层依赖,用npm audit扫描已知漏洞 - 对体积大、副作用强的依赖(如语言服务器),优先考虑作为独立子进程启动,而非直接
require
大型依赖建议解耦为独立服务
像 typescript-language-server 或 jsonc-parser 这类重型依赖,直接 require 进插件主进程会拖慢启动速度,还可能因 Node.js 版本差异(VSCode 内置 Node 版本固定)引发兼容问题。
更健壮的做法是把它抽成一个单独可执行文件或通过 stdio 通信的子进程:
- 构建时把服务二进制或脚本放入插件
out/目录,运行时用child_process.spawn()启动 - 主插件只负责协议桥接(如 LSP),不承担解析逻辑
- 这样既能规避
node_modules体积膨胀,又便于单独升级服务端,也利于跨平台分发
真正麻烦的从来不是“怎么装依赖”,而是“谁在什么时候、以什么方式、用哪个版本去读写同一份共享状态”。插件越复杂,越要提前想清楚模块边界和进程隔离策略。











