返回首页

npm 依赖膨胀:3 个原因和解决方案

本文分解了 npm 依赖增长的三个原因:遗留环境支持、原子架构和过时的 ponyfills。描述了重复问题、供应链风险和清理建议。针对中高级开发者的材料。

npm 依赖在 JS 中的 '膨胀' 的三个原因
Advertisement 728x90

npm依赖树为何臃肿:三大关键原因

JavaScript项目中的依赖树常因过时包和冗余平台特性而膨胀,导致不必要的下载成本、版本冲突和供应链漏洞。让我们探讨三种典型场景来解释这一现象及其解决方案。

遗留环境支持与特定领域问题

许多包如is-stringhasown的存在是为了兼容老旧运行时,如ES3(IE6/7、早期Node.js)。它们实现了缺失的方法:Array.prototype.forEachArray.prototype.reduceObject.keysObject.defineProperty

其他动机包括:

Google AdInline article slot
  • 全局命名空间保护:Node导入原始对象(如Map)以防止覆盖导致的崩溃。类似地,math-intrinsics等包重新导出Math.*
  • 领域兼容性instanceof在iframe和父窗口之间不适用(不同的RegExp构造函数)。替代方案是Object.prototype.toString.call(val) === '[object RegExp]',如chaiis-string中用于new String(val)
const shebangRegex = /^#!(.*)/;
export default shebangRegex;

对大多数中高级开发者来说,这过于繁琐:现代Node(不超过10年)和浏览器无需此类技巧。建议:检查您的browserslist并移除不必要的polyfill。

原子化架构:从理论到问题

“原子化”包的理念是将代码拆分为最小块以便重用。例如,execa的依赖图包含shebang-regex(5行代码)等包。

典型原子化工具:

Google AdInline article slot
  • arrifyArray.isArray(val) ? val : [val]
  • slash:路径斜杠标准化
  • cli-boxes:包含UI元素边框的JSON
  • path-keyenv['PATH'] || env['Path']
  • onetime:一次性函数调用
  • is-wslprocess.platform === 'linux' && /microsoft/.test(os.release())
  • is-windowsprocess.platform === 'win32'

理论上,这简化了CLI构建。但实际上:

  • 一次性使用shebang-regex仅由shebang-command(同一作者)使用;cli-boxes仅由boxen/ink使用。
  • 提升重复项:在nuxt中,重复项如is-dockeris-streamis-wsl(各2个版本)。内联代码可免费复制,无需npm开销。
  • 供应链风险:更多包意味着更多漏洞。去年一名维护者被攻陷影响了数百个依赖。

解决方案:内联简单函数,使用tree-shaking,以及pnpm的严格提升。

已过时的Ponyfill

Ponyfill是不改变全局变量的polyfill,直接导入。对库有用:@fastly/performance-observer-polyfill允许使用PerformanceObserver而不改变环境。

Google AdInline article slot

问题:原生支持出现后它们未被移除。

过时ponyfill示例(每周下载量):

  • globalthis — 用于globalThis(自2019年支持,4900万次/周)
  • indexof — 用于Array.prototype.indexOf(自2010年支持,230万次/周)
  • object.entries — 用于Object.entries(自2017年支持,3500万次/周)

eslint-plugin-react中,一半依赖图由遗留polyfill组成。对库而言:依赖用户端polyfill(如core-js)。添加前检查caniuse.com。

关键要点

  • 优化遗留代码:90%的包不需要ES3/ES5 polyfill;使用typeof而非is-string
  • 原子化有害:内联5行函数以减少重复和攻击面。
  • 审计ponyfill:移除目标运行时支持超过5年的功能包。
  • 工具:使用npm ls --depth=0depchecknpm-check-updates进行分析。
  • e18e倡议:专注于清理过时依赖以提升性能。

实际清理步骤

  • 运行npm dedupenpm prune
  • package.json中添加overrides以强制提升。
  • 使用esbuild/vite配合tree-shaking。
  • webpack-bundle-analyzer监控包大小。

这可在不损失功能的情况下减少包大小20-50%。

— Editorial Team

Advertisement 728x90

继续阅读