lock不住的bug?

2,139 阅读3分钟

做一次技术优化的需求,碰到了好几个依赖相关的问题,而大部分的问题都是与lock文件相关。需要中涉及到将一个旧的依赖库移除,用新的静态资源的方式引入(script直接引用cdn上的js资源)。

Q1. 本地的包管理器与自动化流程中的构建服务用到的包管理器不一致,或者两者版本不一致。

因为提前知晓构建服务中用的是pnpm,所以我也选择了pnpm。但是我在将无用库从package.json中删除之后,准备通过pnpm i更新一下lock文件。结果发现,pnpm-lock.yaml有大量变更。我留意到pnpm-lock.yaml文件中lockfileVersion的变更(5.x -> 6),然后让我找到相关变更文档。

pnpm v8 release changelog中有相关说明

截屏2023-06-26 22.58.40.png

原来是我的pnpm版本不同导致产生了大量的变更。去自动化构建服务中找到包管理器版本(v7.4.1)之后。在切换pnpm版本过程中又遇到了问题:

npm i -g pnpm@7.4.1

终端的反馈表明安装成功。输入pnpm -v,“窝草”,还是8.6.x。 然后又重新来一遍,结果还是一样。在which pnpm之后发现安装路径跟预想的不太一样,醒悟过来之前的pnpm是通过homebrew安装。所以用brew uninstall移除当前pnpm,再用npm安装,成功地将版本号改为7.4.1~

撸起袖子继续干,先get reset --hard HEADpnpm-lock.yaml变更恢复,然后rm -rf node_modules,再运行pnpm i。倒杯水回来,git diff发现:pnpm-lock.yaml的文件变更只是将此次移除的库的lock相关信息移除。😄

尽量保证自动化包管理和开发环境一致,可以通过package.jsonengines进行控制

{
  "engines": {
    "node": ">=16.0.0 <18",
    "pnpm": "7.4.1"
  }
}

Q2. 修改了package.json中文件的版本,但是没有更新pnpm-lock.json文件?

在不了解pnpm-lock.json时,不敢轻易动这个文件,然后会将其变更恢复至之前的状态。不确定你们有没有这么干过,反正之前我干过。然后本地可以跑起来,但是等到自动化构建时就可能包异常导致构建失败,或者构建可以成功但是运行时有报错。

package.json包信息与lock文件中包信息

  1. 完全匹配,lock文件由package.json中的依赖通过install命令生成。✅
  2. pacakge.json升级了版本,或者有改动,但是没有更新lock文件。❎
    下次pnpm i时,lock文件会被忽略,根据package.json中的dependenciesdevDependenciesversion信息安装符合版本控制的最新版本。(语义化版本
  3. package.json升级了版本,然后手动修改了lock文件中的版本。❎
    在生成lock文件时,每个依赖项有一个integrity属性,它的值是根据当前包内容通过SHA-512计算出一个hash值。在install时会验证integrity的正确性。上述行为会导致验证失败,所以这种操作也是不正确的。

这周因为pnpm-lock.json的管理姿势不正确,导致没有锁住版本,有项目在自动化打包过程中一直失败。失败原因就是上面的第二条。bug来源于有2万star非常好用的react动画库react-spring。这个库在9.7.2版本会出现一个构建异常的bug。官方已经在v9.7.3版本中修复了。这个是github issue

在安装新包或者更新package.json中已存在包时,同步更新lock文件,同时用Git保存变化。

Q3: node_modules中安装了同一个包的不同版本?

如果有意为之,比如用过npm install <alias>@npm:<name>有意的安装不同版本,那这个就是不必多说。

这里主要是指无意,且多个版本可能导致一些不好结果,比如某个版本有问题(我遇到的就是这种,还是上面的那个@react-spring库),或者包体积过大等等。

如果遇到这种情况,首先可以通过why命令查看依赖图:

# pnpm|npm|yarn why libraryName
# 比如

pnpm why @react-spring/web

# 会有一下类似的依赖关系
@xxx/xxx-aaa 3.0.54
└── @react-spring/web 9.6.1
@xxx/xxx-bbb 2.3.20
└─┬ antd-mobile 5.1.0
  └── @react-spring/web 9.7.3

然后可以去分析为什么会有这种安装情况:

  • 有可能是上面Q2这种情况导致的?
  • 两个版本是不是差异比较大,各自是符合其被依赖对象的版本控制的?比如其中一个需要5.x的版本,另一个^6.0.0的版本

遇到这种情况有几种方式可以帮你:

  1. 高版本(npm@^9, pnpm@^8, yarn@^2)有dedupe的命令,可以帮你找到合适的版本
  2. 你根据依赖关系,自己判断版本,然后通过package.json中添加 resolutions | overrides 字段,这样就会共用同一个版本的包了。配置如下:
# npm@^8支持overrides

{ 
    "overrides": { 
        "@react-spring/web": "9.6.1" 
    } 
}

# yarn | pnpm 支持 resolutions

{
    "resolutions": { 
        "@react-spring/web": "9.6.1" 
    } 
}

这就是遇到的问题。动动手,总总结,防止脑袋生锈~ 也希望对大家有帮助~