一直都觉得 npm 版本号没什么好注意的,直到今天掉到坑里了,爬了一下午才爬出来,特作此文,加深印象,提醒自己。

某日,用的好好的 Webpack 突然打出来的包某个 entry 不能用了,一直报错 Uncaught TypeError: Cannot read property 'call' of undefined 。代码一顿分析没找到原因,去 Webpack Issue 上搜了一把,还真有不少遇到相同问题的(74997425)。官方维护人员给出的反馈是暂未定位到具体原因,翻看了下面的反馈,有人指出使用 4.9.2 以上的版本都会有问题。

So,cnpm i -D webpack@4.9.2 尝试安装了 4.9.2 的版本,重新打包,问题不再重现,问题解决,提交新的 package.json,美滋滋。

But,还没安稳多久。同事 Kim 表示自己的项目打出来的包还是不正常。怎么会这样呢,我们俩的项目都是一样的,代码都是最新的。于是我重新打包了一次项目,没能重现。于是 rm -rf node_modules,重新 cnpm i,自信打包。

问题复现…What?!怎么会?包不都是一样的吗?笔者一顿猛删 node_modules,下载了各种 webpack 版本,各种 cnpm i,发现打包时好时坏,怎么回事呢?这时一道灵光闪过,会不会是 node_modules 下的包版本不一致呢?仔细对比了同事的 node_modules 发现,他的 webpack 居然是 4.12.0 的!为什么呢?笔者突然想起来,package.json 里面的配置是:

1
2
3
4
5
6
7
{
// ...
"devDependencies": {
// ...
"webpack": "^4.9.0"
}
}

请注意这个 ^ ,罪魁祸首就是这个 ^!它的含义是 不低于当前版本主版本号的最新版本。也就是说,如果当前 webpack 最高版本 4.12.0 ,那么你的 ^4.9.0 会去下载 4.12.0,也就是当前的问题版本,而不是 4.9.0!这也解释了为什么我主动 cnpm i -D webpack@4.9.2 的时候打包正常,而删除 node_modules 重新打包就会出现问题,两种操作下下来的 webpack 版本不一致嘛!

问题定位出来后,我们修改了 package.json,在官方修复该问题之前先锁定版本号:

1
2
3
4
5
6
7
8
{
// ...
"devDependencies": {
// ...
- "webpack": "^4.9.0",
+ "webpack": "4.9.0",
}
}

重新安装&打包,问题不再重现,bug fix!

附 npmjs 官网对语义化符号的说明 https://semver.npmjs.com/