← 中文资源

简体中文版本

揪出撑大前端包体积的重复依赖

列出依赖图里多版本并存的包,追踪各自被谁拉进来,再合并成单一版本。

阅读英文原文

目标

同一个库的两个版本同时进包,意味着双倍字节、双倍解析时间,有时还有两个独立模块注册表把单例状态撕成两半。这种重复在代码评审里完全不可见,因为它是解析器制造的,不是你写的哪行 import 造成的。本食谱把重复版本列出来、按导入方归因、在解析层合并,再用 CI 门禁让这类回归无法静默回归。

步骤要点

  1. 用 pnpm why 或 npm ls 列出多版本并存的包及其依赖路径,确认嵌套的旧版本是被哪个库拉进来的。
  2. 跑构建并出分析报告,量化每个副本的 gzip 体积,把抽象的“重复”翻译成已交付的字节数。
  3. grep 源码里的 import 并结合 why 输出做归因,找出拉进第二份副本的确切导入链。
  4. 在解析层合并:pnpm 用 overrides(可按父包窄化作用域),vite/webpack 用 alias 加 dedupe 列表,重装后重构建。
  5. 加 CI 重复检查脚本遍历整棵依赖树,发现同名不同版本就按包名报错,锁文件一变即评估。

排错提示

override 弄坏旧消费方说明嵌套版本是为 API 差异而存在的,先升级消费方,或收窄 override 作用域并显式测试旧组件再合入;npm ls 干净但产物里有重复是混用模块格式(lodash 与 lodash-es 双入场),用 alias 统一或两都进 dedupe;不升大版本就消不掉重复时先量化 KB,12KB 的重复是工单不是事故,CI 检查会防止它复利增长。

适用边界

解析层去重会改变实际执行的代码,嵌套版本可能事出有因,合并前必须测试受影响导入方;重复检查只抓版本重复不抓普遍膨胀,要与体积预算并存而非替代。

代码示例

# Which packages exist twice, and why?
pnpm why lodash
# old-table-component 1.2.0
# ├─ lodash 3.10.1     <-- nested old copy
# charts-widget 4.1.0
# └─ lodash 4.17.21

# What does that cost in the artifact?
# bundle-report: lodash@3  21.4KB gzip  (dead weight)
#               lodash@4  24.9KB gzip  (the real one)

# Collapse it
pnpm.overrides: { "old-table-component>lodash": "^4.17.21" }
# bundle after: 46.3KB -> 24.9KB gzip for lodash total