首页技术专题博客目录我的收藏关于与联系

第三方库的地狱:依赖管理的那些坑

项目用了 200 多个 npm 包,每次升级都要解决一堆冲突。有些包已经没人维护了,但还在用。有些包功能重复,但都在用。这篇文章聊聊依赖管理的那些坑。

依赖爆炸

项目刚开始,依赖还不多,package.json 里就 20 多个包。但用了一年多,依赖就爆炸了,直接依赖 50 多个,间接依赖 200 多个。

每次 npm install 都要等好几分钟,node_modules 文件夹有 500MB。更烦的是,有些包已经没人维护了,但还在用。

版本冲突

最烦的是版本冲突。A 包依赖 React 16,B 包依赖 React 17,C 包依赖 React 18。三个包都要用,但 React 只能装一个版本。

npm 的话,会装多个版本,但只用一个。用 yarn 的话,会报错,要手动解决。

我们最后用了 pnpm,它用符号链接,同一个包只装一次,但不同版本可以共存。虽然解决了冲突,但 node_modules 的结构变得很复杂。

安全漏洞

npm audit 检查,发现 50 多个安全漏洞。有些是直接依赖,有些是间接依赖。

修复漏洞要升级包,但升级包可能破坏功能。我们试过升级一个包,结果整个项目都挂了。排查了半天,发现是 API 变了。

有些漏洞在间接依赖里,不能直接升级。要用 npm audit fix,但有时候会升级到不兼容的版本。

功能重复

项目里有很多功能重复的包:

  • 日期处理:momentdayjsdate-fns,三个都在用
  • HTTP 请求:axiosfetchrequest,三个都在用
  • 工具函数:lodashramdaunderscore,三个都在用

功能重复,但都在用。想统一,但改起来很麻烦,就一直拖着。

没人维护的包

有些包已经没人维护了,但还在用。比如 request,官方已经废弃了,但项目里还在用。

想换,但改起来很麻烦。不改,又担心安全问题。最后只能硬着头皮用,等有时间再换。

我们的改进

用了一年多,我们做了这些改进:

1. 定期清理

定期清理不用的包,用 depcheck 检查。发现不用的包,直接删掉。

清理了几次,依赖从 200 多个降到 150 多个,但还是很多。

2. 统一工具

统一工具库,比如日期处理只用 dayjs,HTTP 请求只用 axios。其他工具库逐步替换。

替换很慢,但至少方向对了。

3. 锁定版本

锁定依赖版本,用 package-lock.json。这样不同环境装的版本一样,不会出问题。

但锁定版本也有问题,升级很麻烦。每次升级,都要测试一遍,确保没问题。

4. 安全扫描

定期做安全扫描,用 npm auditsnyk。发现漏洞,及时修复。

但修复漏洞很麻烦,有时候要升级很多包,风险很大。

如果重新开始

如果重新做一个项目,我会:

  • 尽量少用第三方库,能自己写就自己写
  • 选维护活跃的库,不要选没人维护的
  • 统一工具库,不要重复
  • 定期清理,不要积累

总结

依赖管理是个大问题,不是简单的安装和升级。版本冲突、安全漏洞、功能重复、没人维护,都是常见问题。

如果你们项目也有依赖问题,建议定期清理,统一工具,锁定版本,做好安全扫描。虽然麻烦,但总比出问题好。

另外,依赖管理要早规划,不要等出问题再处理。等出问题了,处理起来就很麻烦了。