问题现象
前端开发中常常会遇到类似这样的问题:
- 代码没改,重装一下了依赖就报错了。
- 代码一样的,我本地报错,团队其他人不报错。
原因分析
这很可能是依赖出了问题,根因是package.json
中指定依赖时可以范围性的指定,类似下面这样:
{
"dependencies": {
"foo": "1.0.0 - 2.9999.9999",
"bar": ">=1.0.2 <2.1.2",
"baz": ">1.0.2 <=2.3.4",
"boo": "^version",
"qux": "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0",
"asd": "<http://asdf.com/asdf.tar.gz>",
"til": "~1.2",
"elf": "~1.2.3",
"two": "2.x",
"thr": "3.3.x",
"lat": "latest",
"dyl": "file:../dyl"
}
}
官方的说明如下
version
Must matchversion
exactly
>version
Must be greater thanversion
>=version
etc
<version
<=version
~version
"Approximately equivalent to version" See semver
^version
"Compatible with version" See semver
1.2.x
1.2.0, 1.2.1, etc., but not 1.3.0
那么,可能当时你的某一个依赖写成^version
没有问题,但随着这个依赖包的更新,可能作者只动了小版本号,但确引入了破坏性更新,就会对你造成影响。毕竟代码是人写的,版本号也是人定的,总会有考虑不到的地方。
这样,问题的现象就很好解释了:
- 你重新安装了依赖,在你上一次安装依赖和本次安装之间,作者更新了版本。
- 你的队友没有重新安装依赖。
**注意:**因为npm的依赖是层层嵌套的,所以有可能直接依赖的包没有问题,但是你依赖的依赖可能会有这样的问题,最终问题会传导到你的项目里。
解决办法
现象
下面举一个实例,现象是一个Electron应用,打包后运行出错:
排查
在项目中全局查了一下,发现项目并没有使用的到unused-filename
这个包,从上图中的异常栈中其实也可以看到,是electron-dl
这个包引用了它。
- 第一步,我把
electron-dl
的版本固定下来:"electron-dl": "^3.5.2"
→"electron-dl": "3.5.2"
发现依旧报错,说明大概率不是electron-dl
版本更新导致的,它也是被坑了。
再在node_modules
中找到electron-dl
这个依赖,直接修改它的package.json
- 可以看到它引用了unused-filename,并且没有固定版本号,我们直接修改一下。
"unused-filename": "^2.1.0”
→"unused-filename": "2.1.0”
- 再次打包,问题不存在了。
解决
问题找到了,但这是本地的打包,我们可以直接修改node_modules
中的文件。如果你用了CI/DI工具,为了改node_modules
中的文件而定制构建脚本,绝对是下下策。
此时只要把package-lock.json
用好就行,把package-lock.json
也加入到git的版本控制中是一个好的习惯,package-lock.json
会固定好依赖以及依赖的依赖,如下:
这样,你就不需要改node_modules
中的文件了,在package-lock.json
中改就行。
package-lock.json
会在第一次npm i
时自动生成,把依赖以及依赖的依赖的版本固定下来,后续安装再多次也是使用你第一次的所有版本。
但需要注意的是 cnpm i
不会生成 package-lock.json,即使现在目录里有 package-lock.json 它也不会使用。