ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

把 node_modules 裁到 88 个包:Electron 安装包瘦身三十三兆

把 node_modules 裁到 88 个包:Electron 安装包瘦身三十三兆 桌面应用分发最先要对付的就是体积。安装包太大下载失败率随网络质量起伏更新等待也在拉长客户对这软件怎么这么大的抱怨永远不会缺席。我们给主力产品做了一轮体积治理没有重构一行业务代码安装器从 242MB 降到 209MB构建产物目录从 75MB 的第三方依赖收缩到 17.9MB。核心手段是闭包可达性分析驱动的依赖裁剪。这里把完整过程和踩的坑记录下来。现象安装包比业务代码大四个数量级先量化问题。一个 Electron 桌面应用安装器 242MB其中 Chromium 运行时约占 200MB——这是 Electron 的固有底座成本。剩下四十多兆里应用自身代码只有约 200KB其余全部是 node_modules 的打包产物436 个包、75MB未压缩。也就是说真正我们的代码在体积构成里几乎不可见。对体积做治理等于对第三方依赖做治理。但直接删包有致命风险删错一个轻则某条业务功能静默报错重则打包产物在特定分支才崩溃——测试覆盖不到的角落永远存在。所以治理的前提是先回答哪些包可以证明没人用哪些包是不敢删的。归因安装器里到底装了什么拆开安装包NSIS逐项清点构成大致分三层Electron 底座约 200MB。框架自带删不掉只能靠版本升级缓慢消化。打包进 asar 的第三方依赖75MB436 个包。这是治理主战场。应用自身代码与资源不到 1MB。依赖层的 75MB 又有两种成因处置方式完全不同。一种是死代码包还在 package.json 里但代码里早就没人引用——通常是某次重构把调用点删了依赖声明忘了跟着删。另一种是有效但肥大比如语言包、测试夹具、预编译多平台二进制被整包打进了产物。后者需要配置打包工具只保留用到的部分前者才是删包的对象。全量复制其实是一笔历史债早期打包脚本图省事直接整目录拷贝 node_modules宁滥勿缺。这个默认配置安全但浪费一旦形成没人愿意回头逐包核实——直到体积变成客户投诉才被迫来做。凡是安全但粗暴的打包配置都建议在还不难受的时候先立个审计。首道工序闭包可达性分析删死代码包人工 grep 不可靠包的引用可能藏在配置、字符串拼接、动态 require 里也可能通过传递依赖被间接使用。我们改用程序化判定以入口文件为根把 import/require 当作图的边做可达性遍历凡是图上不可达的包才进入候选删除名单。js// 闭包可达性从入口出发遍历依赖图不可达包进候选名单const entryPoints [./src/index.js, ./server-go/main.go]; // 前端入口与伴生二进制源码根function walkGraph(roots) {const seen new Set();const stack [...roots];while (stack.length) {const mod stack.pop();if (seen.has(mod)) continue;seen.add(mod);for (const dep of extractRequires(mod)) stack.push(dep); // 解析 import/require 静态目标}return seen;}两个要点。其一遍历必须从多入口开始Electron 应用至少分主进程、渲染进程两个根如果应用带独立后端后端入口也要计入。漏一个入口可达性结论就是反的——工具会把只有后端在用的包误判为死包。我们就在初版分析里栽过这个跟头后端入口没计入候选名单里混进了前端链路真正依赖的几个包好在发布前的完整性校验环节把它们抓了回来下文细说。其二静态分析有天然边界动态 require比如某些插件按配置名拼接路径加载的模块在图上没有可见的边可达性分析看不见它们。这类包没法靠静态遍历证明死活只能人工逐个定性。所以遍历产出的只是候选名单不是删除名单——每个候选要么人工确认确无引用要么被完整性闸兜底拦下。跳过这一步直接按候选名单批删迟早出事。第二步人工核对与语言包收敛候选名单逐个过查配置引用、查字符串引用、查打包工具的隐式约定双人都确认确无人用才移出依赖声明。一轮下来 436 个包砍到 88 个75MB 收敛到 17.9MB。另一个大头是多语言资源。框架 locale 目录默认带 55 种语言文件约 41MB。产品实际只支持中英两种配置裁剪后只剩 2 个文件约 1MB。这类默认全带的资源字体、图标集、时区库同理在打包配置层面一行白名单就能解决是体积治理里性价比最高的动作值得每次升级后复查一遍有没有被新依赖重新带进来。第三步完整性硬闸——把删多了变成发布失败裁剪类改造最大的风险从来不是删不够而是删多了——少一个包应用可能在某个没人点到的功能里才炸。我们把防线做成发布链路上的一道闸而不是靠测试用例穷举打包完成后用真实产物环境执行一遍主进程入口与全部业务路由的模块加载任何一个 require 解析失败发布直接终止。这道闸在自动化里叫afterPack 完整性校验原则只有一条删包后的正确性不靠人脑记账靠机器重新走一遍加载路径。它不验证业务逻辑对错但保证没人会在用户机器上第一次发现某个模块不见了。前面说的后端入口遗漏就是被这道闸在发布前拦下来的——如果只依赖测试用例那个包覆盖的分支未必有人点。NSIS 层再配一组必然存在条目断言关键文件必须出现在安装包条目表里出现即证明打包链没把裁掉的模块错误引用进来也没把该带的资源弄丢。结果与边界发布验证包体积 242MB 降到 209MB降幅 13.6%下载实测字节与构建产物 SHA 一致安装包在干净 Windows 环境跑通全功能路由。收益更直接的是开发体验依赖目录从 75MB 缩到 17.9MB本地重装、增量打包的速度都明显变轻。对209MB 还是太大的追问回答要诚实大头是 Electron 自带的 Chromium占八成以上。迁移到 Tauri用系统 WebView能把底座压到十几兆但那意味着主进程架构、更新机制、系统兼容层全部重写。对一个已有线上用户群的产品这是一次以季度计的重构不是一次体积优化。该说不的时候要说不。复盘三条可迁移的经验一是先归因再动手。把 242MB 拆成底座 依赖 自身三层才知道哪 13% 是可以工程化拿下的哪 80% 是架构成本。二是可达性分析要喂全入口。主进程、渲染进程、伴生服务漏一个方向结论就反过来——我们的初版名单就是这么错的。三是裁剪必须配完整性闸删除操作的正确性不靠人脑记账靠机器重新加载一遍。闭包图是地图不是领土地图外的动态 require 要靠闸门兜底。体积优化是典型的看起来谁都会、做完才发现全是细节的活。数字背后真正值钱的是那套任何删减都要可证明的机制。参考文章10 款免费微信自动回复机器人横向盘点2026 版微信 AI 自动回复工具怎么部署安装配置全流程
返回列表