关于npm版本管理的坑
版本号规则, node version
package.json, package-lock.json
nvm, npm, yarn
npm 版本号规则
参考:Semantic Versioning
所有的 npm 包都采用以下规则定义版本号(称为语义化版本):
所有的版本号都用三个数字进行标记:
x.y.z
- 第一位 x 代表主版本(major version):更新API(不兼容)
- 第二位 y 代表副版本(minor version):增加功能(向下兼容)
- 第三位 z 代表补丁版本(patch version):修复 bug(向下兼容)
那么,我们在 package.json
中常见的 ^x.y.z
、~x.y.z
之类的规则就容易解释了:
^
:^0.13.0
代表同意 patch 和 minor 版本的更新,也就是当npm update
时该版本可以更新到0.13.1
、0.14.0
等~
:^0.13.0
代表同意 patch 版本的更新,也就是当npm update
时该版本可以更新到0.13.1
,但不会更新到0.14.0
>
/>=
/<
/<=
/=
:语义较为直接,不赘述-
:可以指定接受的版本范围,如2.1.0-2.6.2
||
:可以给规则集取并,如< 2.1 || > 2.6
- 无符号标记:指定某个确定版本
- latest:最新的可用版本
package.json、package-lock.json、yarn
经常会出现按照同一个 package.json
在不同人的机器上 npm install
出的环境不一致的问题,这其中一部分原因就是由于上面所描述的版本号规则,导致不同时间下载的包版本可能不同。
那么,在 package.json
中把所有包的版本都严格指定就好了?
很遗憾,还是不行。
因为这些包自己的 package.json
中又引用了别的包,还是无法保证第二层第三层…包的版本一致。
于是 npm 引入了 package-lock.json
这个文件,正如它的名字“锁”,它严格锁定了所有包的版本号(包括第二层第三层…的包),甚至还指定了每个包的下载地址。如果项目中存在 package-lock.json
,npm install
会按照它而不是 package.json
进行安装。
所以一个比较好的实践是,多人协作时把 package-lock.json
也放到 git 上。
再之后,yarn 出现了,yarn 用一个 yarn.lock
文件做了和上面 package-lock.json
同样的锁定版本工作,而且这个文件是默认创建更新的,也就解决了需要维护 package.json
和 package-lock.json
两个文件的问题。
yarn 还有一堆优点,这里就不赘述了,总之新项目用 yarn 肯定要比用 npm 方便,但对于一些没有用 yarn 的老项目,就要注意上面的版本管理问题了。
node-sass 经常产生的 node 版本问题
对于老项目,还有个很痛的地方,node-sass,特别是 node-sass 在 windows 上安装。需要下载的东西多且要翻墙、需要 gyp、需要 windows-build-tools……中途万一哪里卡住想要推倒重来,却会发现 npm uninstall
不能完全卸载 windows-build-tools,还要手工卸载手工重装,python27 还好,寻找老版本的 visual studio c++ 简直是噩梦……
而当你搞定了以上一切,以为终于能顺利安装时,又遇到了一堆堆的 Build failed with error code: 1
……
其中一个问题坑了我一天时间,最终在 [Unsupported] Installing node-sass 4.11.0 with Node 12 找到了答案。
node-sass 4.11.0,不兼容 node 12!
升 node-sass 版本,别的开发者可能会受影响;降 node 版本,强迫症浑身难受……
然后我就找到了下面这个神器:
nvm
没错,Node Version Manager,管理 node 版本的工具!windows 版的地址:nvm-windows。
按照说明下载安装就行了,需要注意的几个小地方:
- 安装前需要删除本地已经安装的 node 和 npm(如何彻底卸载请自行 google),如果有一些 npm config 可以先备份
npmrc
- 如果你有多个版本的 node,需要对每个版本都重新安装全局包们,它们不会在不同 node 版本中共享
- 勤用
node -v
检查版本,如果第一条没搞好可能 nvm 根本不会起效…
于是我把 node 版本切到 11 再去跑老项目,终于一路通畅无阻啦!
一点点反思:package.json
中其实可以指定 node 版本号,我感觉这才是最根本的解决方案,不然只能靠口耳相传“你用的啥版本”、“我咋跑不起来呢”……