package.json版本管理的相关思考

发布时间:2023年12月18日

一、前言

线上部署打包时,自己下载了最新依赖,于是线上依赖版本和研发本地依赖版本不同,不巧的是最新依赖有 bug 而本地早先下载的没有。导致这种版安装的依赖版本差异的决定性原因则是 package.json 没有写死版本号,而是使用允许根据市场版本更新的指令符号 ^~

二、package.json 中的 ^ ~

^ 意思是要更新【次版本】,当市场有更新的版本时,例如:package.json 中是"^2.1.0",库可能会更新到2.2.0的最新版本,但不会更新到3.0.0版本。

~ 意思是要更新【补丁版本】,当市场有更新的版本时,例如:package.json 中是"~2.1.0",库可能会更新到2.1.1的最新版本,但不会更新到2.2.0版本。

版本号前面啥也没有,表示写死了版本号,无论何时何地安装的依赖版本只会是这个。

三、怎么锁定工程依赖的版本

在实践中,工程依赖的版本锁定,可能会有两方面的考虑,一是通过包管理工具的 lock 进行版本依赖锁定, 二则是通过在 package.json 中写死版本号来“绝对锁定”依赖版本。依赖版本的锁定,是必须要考虑, 否则一个差异和不幸可能需要浪费大量时间去定位由此导致的 bug,那将是痛苦而不值得的,尽管发生的机会比较小。

3.1、package.json 的锁定

毫无疑问,package.json 具有依赖版本的决定权。是否在安装依赖时,下载新版本,是否修改 lock 版本,是由 package.json 中附带 ~ ^等命令符号结合市场最新版本决定的, 在决定性因素上,与使用的包管理工具并无多大关系,无论是 npmyarnpnpm

只要,package.json 写死版本号,版本号前不携带那些 ~ ^等符号,那么无论何时何地何人安装依赖,依赖版本都会是一致的。

因此,在功能已经开发完毕,进入运维阶段的前端工程项目,如果希望减少由于依赖版本差异带来的莫名其面的 bug,那么写死 package.json 中版本号是可行可靠的。如果确有需要升级依赖版本,再单独手动去升级。项目上线转运维阶段后,需要批量更新依赖,从而使用新依赖的新功能的可能性较小, 而运维中项目保证项目的稳定才是更重要工作,毕竟“还能跑就行”。

3.2、yarnnpm 等的 lock 锁定

矛盾是总是存在的,总有不希望一个一个手动更新依赖的需求,总有希望“一键更新全部依赖”的场景。这种时候,package.json 中写死版本号,则不是期望的。那么某种程度上的依赖本锁定则出现了,这就是通过包管理工具的 lock 来锁定,例如 yarnyarn.locknpmpackage-lock.json, 以及 pnpmpnpm-lock.yaml

据我观测一些知名的开源项目,通常也不会全部一锤将版本号都写死中 package.json,并且通常让Git记下 lock 的变更记录。例如:

vuejs/vuepnpmlock

facebook/reactyarnlock

axios/axiosnpmlock

dcloudio/uni-appyarnlock

didi/LogicFlowyarnlock

quilljs/quillnpmlock

3.3、yarn.lockpackage-lock.json 下载新依赖上的区别

包管理工具的 lock 也具有某种程度上的“依赖版本锁定”功能,尽管不同的工具的 lock 表现具有差异。例如当 package-lock.json 存在时,即使市场上有比 package-lock.json 中锁定版本更新,且 package-lock.json 中存在 ^ ~ 允许更新, 安装的版本也只会是 package-lock.json 中锁定的版本,不会自动下载更新的版本。当然当 package.json 中版本被手动更新,会触发的 package-lock.json 连带变更。

yarnyarn.lock 的“版本锁定”的则表现不同,当市场有比 yarn.lock 中更新的版本,且 package-lock.json 中存在 ^ ~ 允许更新, 那么 yarn 会自动安装比 yarn.lock 更新的版本并且主动修改 yarn.lock

从这个差异角度看,package-lock.json 的“版本锁定”更可靠,可以起到依赖版本保持一致的作用,而 yarn.lock 则不具备。

3.4、让Git记下 lock 的变更记录

既然 yarn.lock 无法帮助我们“锁定”版本,那么 yarn.lock 的意思而在?我并不清楚 yarn.lock 设计全部意义,但我可以确定的一个价值是: Git记下 lock 的变更记录,有助于追踪使用的依赖版本记录,有时会很有作用,例如定位某类bug时。

即使 lock 会被修改,它的存在也会很有价值,例如:证明此前被 lock 的版本在本工程是可用的。因为会存在某个新下的最新版本存在缺陷或不符合本工程的需求的情形。这个新版本缺陷可能会导致工程无法运行或运行异常。

一个例子是,新同事安装工程出现工程运行异常,而旧同事正常,且通过 git 证明业务代码无差异,package.json 也无差异,此时差异会体现在 lock 的版本。此时要想使用最新且能确保本工程正常运行的依赖版本,那么旧同事 lock 的依赖版本就是答案。

package.json 中的版本虽然可用,但由于具有时间跨度的不确定性,可能会比 lock 的要旧很多。

知名的例子是 vue-routerissues #2881 中提到的,在升级了 Vue-Router 版本到3.1.0及以上之后,页面在跳转路由控制台会报Uncaught (in promise)的问题,从而导致某些场景的跳转异常。

四、小结

总结上述简单的分析和讨论,小结如下:

package.json 具有锁定依赖版本的决定权,包管理工具不具有。

package.json ^ 意思是要更新【次版本】,~ 意思是要更新【补丁版本】。

yarnyarn.locknpmpackage-lock.json 对“锁定依赖版本”表现不同,package-lock.json 的“锁定效果”更可靠。

Git记下 lock 的变更记录是有意义的。一些知名开源项目都让Git记下 lock 的变更记录。

五、最后

本人每篇文章都是一字一句码出来,希望对大家有所帮助,多提提意见。顺手来个三连击,点赞👍收藏💖关注?,一起加油?

文章来源:https://blog.csdn.net/u012804440/article/details/135052360
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。