asar打包是vscode插件动态require场景下最可行的体积压缩手段,通过将node_modules归档为单文件提升安装、启动性能并降低内存占用,但需排除含原生模块、fork调用或fs.watch依赖的包。

直接用 asar 打包 node_modules 是目前对动态 require 场景最可行的体积压缩手段,比盲目删依赖或改构建工具更稳。
为什么 rollup/webpack 不适用于多数 VSCode 插件
VSCode 插件运行时经常依赖动态模块加载(比如 require(extensionPath + '/lib/worker.js') 或插件市场拉取的远程语言服务器),而 rollup 等工具在构建期无法静态分析这类路径,导致打包后 Module not found 报错。
- 插件中若含
require('./' + name)、require(path.join(...))、或通过fs.readFileSync读取并eval的 JS 文件,基本排除构建工具方案 -
vsce package默认把整个node_modules复制进.vsix,文件数超 10 万时,解压和启动耗时飙升 - 即使启用
.vscodeignore,也仅跳过未引用的顶层包,无法解决内部嵌套依赖的碎片化问题
asar 打包的具体操作步骤
核心是让 vsce 把 node_modules 打成单个 node_modules.asar 文件,而非数万个小文件。VSCode 原生支持 asar 加载,无需额外适配。
- 安装
asar:运行npm install --save-dev asar - 在
package.json中添加脚本:"vscode:prepublish": "asar pack node_modules node_modules.asar" - 确保
vsce package执行前先运行该脚本(vsce会自动识别vscode:prepublish) - 检查生成的
.vsix:解压后应只含node_modules.asar,不再有原始node_modules目录
注意:需在 asar pack 后手动删除原 node_modules,否则 vsce 仍会把它一起打包进去——这是最容易漏掉的一步。
哪些依赖必须保留在 asar 外
不是所有模块都适合打进 asar。以下三类必须保持解压状态,否则运行时报错:
- 含原生二进制的包(如
fsevents、sqlite3):asar 不支持直接执行 native addon,需保留.node文件可读路径 - 被
child_process.fork()调用的 JS 文件:Node.jsfork不接受 asar 内路径,会提示Error: ENOENT - 需要
fs.watch监听的目录(如某些语言服务器的临时缓存目录):asar 是只读归档,无法触发文件系统事件
处理方式:用 asar unpack-dir node_modules/some-pkg ./out/some-pkg 单独解压,再在 vscode:prepublish 脚本中合并进最终产物。
体积与启动性能的实际变化
实测一个含 117,317 个文件、185.5 MB 的 node_modules,asar 打包后变为单个 102 MB 的 node_modules.asar,同时带来三项关键改善:
-
.vsix体积下降 46%,用户安装耗时减少 75% 以上(网络传输 + 解压 IO 双降) - 插件启动时模块加载速度提升:Node.js 读单个大文件比遍历数万小文件快得多
- VSCode Extension Host 内存占用降低约 12%:减少了大量文件句柄和缓存元数据
但要注意:asar 并不压缩代码内容本身(只是归档),真正减体积得靠删冗余依赖或换轻量替代品——Import Cost 插件这时才派上用场,它能帮你定位 import 行里哪个包实际拖了后腿。











