常规的开发,常规的代码,不动如山的CI,忽然发生了错误,致使失败,出现如下错误:node
1 |
Build failed: [BABEL] /xxx/xxx/yyy/.xxx.js: You gave us a visitor for the node type OptionalCallExpression but it's not a valid type |
本地调试之,赫然出现了不同的错误:npm
1 |
Build failed: Cannot find module '@babel/runtime/core-js/object/keys' |
观察了一下package.json
,含有"babel-runtime": "^6.9.2"
,因而乎开开心心的安装了下@babel/runtime
=> npm install @babel/runtime
。
BOOOOOM!继续报错,寻遍 issue 未发现错误缘由以及真正的解决办法,TnTjson
查看了下框架包,查找了下项目依赖包的依赖包,发现使用了@babel/runtime@7.0.0-beta.41
的版本,莫不是版本问题?!换之,修改了下package.json
文件以下:babel
1 |
- "babel-runtime": "^6.9.2" |
常规rm -rf node_modules && cnpm install
,小段时间的等待以后,发现错误并无消失,奇了怪了~~框架
继续查看依赖包的依赖包,发现它要7.0.0-beta.41
,而在个人node_modules/
黑洞里的@babel/runtime
却安装的是7.0.0
版本,Bingo,问题找到了,锁个版本,修改以下:ui
1 |
- "@babel/runtime": "^7.0.0-beta.41" |
常规rm -rf node_modules && cnpm install
以后,问题消失了,部署跑CI瞧一下,问题解决。spa
简单的一个问题,在知道缘由以后。若是不知道缘由呢??(此处有个黑人问号)版本控制
幸亏我知道些npm
版本的控制规范,才得已比较早的定位问题并解决之,带着这份小确幸,从新整理了下npm
包管理器的版本管理规范(NPM Version Management Specification)。调试
SemVer
(Semantic Versioning,语义化版本控制)是Github起草的一个语义化版本号管理模块,它实现了版本号的解析和比较,规范版本号的格式,它解决了依赖地狱的问题。code
语义化版本控制,顾名思义,就是让版本号更具备语义,能够传达出关于软件自己的一些重要信息而不仅是简单的一串数字。
1 |
主版本号(Major).次版本号(Minor).修订号(Patch) |
每一个部分都为整数(>=0
),按照递增的规则改变。
基本版本格式
的后面,做为延伸
判断优先层级时,必须把版本依序拆分为主版本号、次版本号、修订号及先行版本号后进行比较。由左到右依次比较每一个标识符号,第一个差别值用来决定优先层级(其中字母链接号以ASCII排序进行比较、其余都相同时栏位多的先行版本号优先级较高)。如:
1 |
1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1。 |
锁定版本号
1.0.0
: 锁定了版本只能为1.0.0
指定版本范围,甚至能够经过||
组合多个比较器
=1.2.7 <1.3.0
中包括1.2.7
、1.2.8
、1.2.99
等等,但不包括1.2.6
、1.3.0
或1.1.0
等等1.2.7 || >=1.2.9 <2.0.0
中包括1.2.7
、1.2.9
、1.4.6
等等,但不包括1.2.8
或2.0.0
等等连字符表示版本号范围,表示的是一个闭区间
1.2.3 - 2.3.4
至关于 >=1.2.3
和 <=2.3.4
能够替代主版本号.次版本号.修订号
三段中任意一段,表示该位置版本号没有限制;另外缺省三段中任意一段与用x
、X
或*
替换该段效果相同
*
至关于 >=0.0.0
,表示任何版本号1.X
或1.x
至关于 >=1.0.0 <2.0.0
,匹配到主版本号1.2.*
至关于 >=1.2.0 <1.3.0
,匹配到主版本号和次版本号""
(空字符串) 至关于 *
,即至关于 >=0.0.0
1
至关于 1.x.x
,即至关于 >=1.0.0 <2.0.0
1.2
至关于 1.2.x
,即至关于 >=1.2.0 <1.3.0
容许小版本迭代
eg.:
~1.2.3
:>=1.2.3 <1.3.0
~1.2
:>=1.2.0 < 1.3.0
(至关于1.2.x
)~1
:>=1.0.0 <2.0.0
(至关于1.x
)~0.2.3
:>=0.2.3 <0.3.0
~0.2
:>=0.2.0 <0.3.0
(至关于0.2.x
)~0
:>=0.0.0 <1.0.0
(至关于0.x
)~1.2.3-beta.2
:>=1.2.3-beta.2 <1.3.0
(注意,在1.2.3
版本中,容许使用大于等于beta.2
的先行版本号,而除1.2.3
以外的版本号不容许使用先行版本号,因此此处1.2.3-beta.4
是容许的,而1.2.4-beta.2
是不容许的)容许大版本迭代
0
那一版本位+1
迭代(左闭右开);+1
迭代eg.:
^1.2.3
:>=1.2.3 <2.0.0
^0.2.3
:>=0.2.3 <0.3.0
^0.0.3
:>=0.0.3 <0.0.4
^1.2.x
:>=1.2.0 <2.0.0
^0.0.x
:>=0.0.0 <0.1.0
^0.0
:>=0.0.0 <0.1.0
^1.x
:>=1.0.0 <2.0.0
^0.x
:>=0.0.0 <1.0.0
^1.2.3-beta.2
:>=1.2.3-beta.2 <2.0.0
(注意,在1.2.3
版本中,容许使用大于等于beta.2
的先行版本号,而除了1.2.3
以外的版本号不容许使用先行版本号,因此此处1.2.3-beta.4
是容许的,而1.2.4-beta.2
是不容许的);^0.0.3-beta
:>=0.0.3-beta <0.0.4
(同上,此处0.0.3-pr.2
是容许的)看到这,聪明的你必定想到了package-lock.json
或是yarn.lock
。
在npm
的版本>=5.1
的时候,package-lock.json
文件是自动打开的,意味着会自动生成,package-lock.json
(官方文档)能够理解为/node_modules
文件夹内容的json
映射,并可以感知npm
的安装/升级/卸载的操做。能够保证在不一样的环境下安装的包版本保持一致。听上去很不错哈,实际使用中,大部分它的表现确实不错,但是如上述问题:我手动修改了package.json
文件内依赖的版本,package-lock.json
就没那么聪明(至少目前是,将来会不会变聪明就不可知了),且不会变化。因而BOOOOOOM~~~~
SO
若是你真的想保证你的包版本在各个环境都是同样的话,请修改下package.json
中的依赖,去掉默认前面的^
,固然这样的话,你就无法自动享受依赖包小版本的修复了,问题来了,在什么状况下选择哪种呢?
^
来享受包的最新功能和修复。这也是推荐的。patch
)作出不兼容更改(不兼容更改在beta
等先行版本中必定[墨菲定律]会发生),那么这个时候,你应该把这个依赖包的版本在package.json
上锁住版本,而不该该把它交给package-lock.json
来处理beta
等先行版本依赖包,由于若是那是你的私有项目,它会在将来的某一刻坑害了你,若是这是你的共有项目,那么,它必定会在将来的某一刻对你的全部用户作出致命的坑害行为!(beta
包就是不负责任的流氓包,玩觉爽就好 ^o^)最后:rm -rf node_modules/ && npm install
大法在你使用package-lock
的状况下,请更换为:rm -rf node_modules && rm -rf package-lock.json && npm install
。