项目越大,依赖越让人头疼
去年我们团队接手一个老系统重构,一开始估摸着三个月能搞定。结果第一个月就卡在了依赖上。光是 package.json 里列的第三方库就有 180 多个,其中一半还是间接依赖。更离谱的是,开发环境跑得好好的,一到测试环境就报错,查来查去发现是某个底层工具包的版本冲突。
这种问题在大项目里太常见了。人多了,模块多了,每个人引入个工具看似无害,可积少成多,最后就成了“依赖地狱”。
统一入口,别让谁都能加依赖
后来我们定了条规矩:所有新引入的外部依赖必须经过技术评审。不是为了卡流程,而是得问清楚——这玩意能不能用内部已有的方案替代?是不是长期维护的项目?文档齐不齐全?
比如有次前端同事想引入一个新的状态管理库,理由是“语法更优雅”。但我们一看周下载量才几千,GitHub 上 issue 堆着没人回,果断劝退。最后用已有的 Redux 中间件解决了问题,省了后期维护成本。
锁定版本,别迷信 ^ 符号
很多人图省事,装包时默认带 ^,觉得能自动更新小版本很省心。可现实是,某个“小版本”更新可能偷偷改了 API,导致整个构建失败。
我们现在一律要求使用 ~ 或直接锁死版本号,配合 package-lock.json 提交到仓库。CI 流水线一旦检测到锁文件没更新,直接拒绝合并。
{
"dependencies": {
"lodash": "~4.17.21",
"axios": "0.26.1"
}
}定期做依赖体检
每个月我们都会跑一次 npm outdated 和 npm audit,不是为了立刻升级,而是掌握风险清单。高危漏洞必须处理,低优先级的也得登记进技术债看板。
有一次扫出一个被废弃的库(deprecated),虽然还在用,但作者早就不管了。我们花了两周把它替换成社区活跃的替代品,避免了后续可能出现的安全问题。
内部包也要管起来
除了第三方,项目里的子模块之间也有依赖。我们把通用逻辑抽成私有 npm 包,发布到公司 Nexus 仓库。每个包有自己的版本号和变更日志,谁改了什么一目了然。
刚开始有人嫌麻烦,说“我改个工具函数还得发版?”时间久了才发现,这样反而减少了扯皮。上线出问题,直接查版本差异,不用翻几十个提交记录找是谁动了共享代码。
工具辅助,别靠人肉记
现在项目根目录下有个 deps-check.js 脚本,每次提交前自动检查是否有未声明的依赖或重复引入。还接入了 Dependabot,重要依赖有更新就自动提 PR,附带测试结果。
这些自动化手段看起来花时间搭建,但比起半夜被报警电话叫醒处理构建失败,这点投入根本不值一提。