业务系统是否该冻结 npm 依赖?

如何冻结 npm 依赖?

  • yarn: 执行 yarn 命令后默认会生成一份 yarn.lock 文件,之后的 npm 包版本安装都会遵照 yarn.lock 中的版本描述(在执行 yarnyarn updateyarn addyarn remove 之后会自动将 package.json 的依赖变动更新到 yarn.lock 中)
  • npm: 执行 npm shrinkwrap 命令后生成一份 npm-shrinkwrap.json 文件,之后的 npm 包版本安装都会遵照 npm-shrinkwrap.json 的版本描述;而从 npm 5.x 版本开始,执行 npm install 命令之后默认会生成一份 package-lock.json 文件,作用与 npm-shrinkwrap.json 相同(在执行 npm installnpm update 之后会自动将 package.json 的依赖变动更新到 package-lock.jsonnpm-shrinkwrap.json 中)
  • 直接在 package.json 中指定具体的依赖版本

依赖冻结与不冻结的优劣

  • 冻结依赖:

    • 可以保证开发、测试和线上的依赖一致,避免由于三方包依赖不一致而引入的 bug
    • 可以缩短测试周期,加速上线
    • 缺点:难以发现某版本依赖的潜在 bug,对于比较滞后的版本依赖,升级成本较高
  • 不冻结依赖:

    • 可以保证依赖的版本是较新的版本,某些低版本的依赖存在的潜在 bug 可以通过自动升级解决
    • 可以减少手动升级带来的成本
    • 缺点:需要依赖靠谱的三方包,测试周期长

Q & A

  • Q: 如何判断一个 npm 包是靠谱的?
    A: 高质量的 npm 包一般有以下几个特征:

    • 版本为 1.x 以上的稳定版本
    • 版本更新遵循 semver 语义化
    • 有较大的下载量
    • github star 数量多
    • 文档说明比较完善
    • 测试覆盖率和通过率高,最好都是 100%
    • 维护者的知名度高
    • github issue 处理效率高
  • Q: 如何解决不冻结依赖时,开发、测试和线上的代码打包依赖不一致的问题?
    A: 最佳解决方案是保证测试和线上使用的包是同一份包。但在有些 case 下需要额外处理,比如对于使用了 github flow 开发流程,往往是测试时候在 a 分支打包,而最后上线的时候会将 a 分支合并到 master 分支,然后重新打包部署,这个时候需要测试人员重新对合并后的 master 新包做一次回归测试方可发上线,这种做法带来的负面影响是会导致测试周期增加

  • Q: 采取冻结依赖方式带来的升级成本过高如何处理?
    A: 一旦项目采取了冻结依赖的方式,后续升级会带来很多的风险,建议定期升级,然后对升级后的包进行回归测试

  • Q: 有些‘冷门’的功能,可能无法找到靠谱的包,不冻结依赖如何处理这种 case?
    A: 使用不冻结依赖的前提是项目引入的依赖是靠谱的,如果遇到了题述的 case,有两种解决方案:

    • 1.简单的功能可以自己手写实现
    • 2.如果想引用一些不靠谱的包,在 package.json 中指定该包的具体版本
  • Q: 使用依赖冻结的方式,package-lock.jsonyarn.locknpm-shrinkwrap.json 文件是否该提交到 git 仓库中?
    A: 建议提交。对于多人开发的系统,提交版本冻结描述文件可以保证使用的版本一致性并且方便依赖的重建