锁定NodeJS项目的依赖库
今天一上班,顺手点了一次构建整个项目,结果发现项目中的javascript编译报错,而且报的错莫名其秒。
1 |
undefined is not iterable! |
---|
搜遍互联网才在babel的twitter上找到了这个问题的说明。
If you are getting an
undefined is not iterable!error, please
npm install babel-types(to use v6.8.1). If necessary, clear node_modules
看情况应该是babel相关的依赖自动升级导致的错误,这里鄙视一下NodeJS生态里的npmjs.com上的库,质量真的是参差不齐,明明安装的是兼容的版本,可实际上很有可能由于某个依赖的升级导致整个项目编译失败。
实际上我之前已发现了这个问题,当时的方案是在package.json里将所有依赖的包指定一个确定的版本号,如下如示:
"dependencies": {
"babel-polyfill": "6.3.14",
"before-unload": "2.0.0",
"bootstrap": "3.3.4",
"bowser": "1.0.0",
"browser-audio": "1.0.2",
"classnames": "2.1.2",
"cropper": "0.11.0",
"extend": "3.0.0",
"fancybox": "3.0.0",
"favicon-notification": "0.1.4",
"flux": "2.0.3",
"fullscreen": "1.0.0",
"immutable": "3.7.5",
"inherits": "2.0.1",
"jquery": "1.11.3",
"jquery-textrange": "1.3.3",
"jwt-decode": "1.4.0",
"keymirror": "0.1.1",
...
}
原以为这样依赖的版本号就固定了。但实际上在NodeJS生态里大量第三方库其package.json文件是这样的:
"dependencies": {
"acorn": "^3.0.0",
"async": "^1.3.0",
"clone": "^1.0.2",
"enhanced-resolve": "^2.2.0",
"interpret": "^1.0.0",
"loader-runner": "^2.1.0",
"loader-utils": "^0.2.11",
"memory-fs": "~0.3.0",
"mkdirp": "~0.5.0",
"node-libs-browser": "^1.0.0",
"object-assign": "^4.0.1",
"source-map": "^0.5.3",
"supports-color": "^3.1.0",
"tapable": "~0.2.3",
"uglify-js": "~2.6.0",
"watchpack": "^1.0.0",
"webpack-sources": "^0.1.0",
"yargs": "^3.31.0"
}
可以看到~
表示该依赖可能会自动更新至最近的minor版本,^
表示该依赖可能会自动更新至最近的major版本。
这样就存在问题了,这里我用示例简单说明一下。
最开始项目是这样的,其中A使用^
依赖于B
proj 1.0.0
A 1.1.0
B 1.2.0
某一天B的维护者发布了一个新的版本1.3.0
,但他并没有经过完备的测试来保证一定是与1.2.0
版本是兼容的。项目的维护者又手贱地执行了下npm install
或npm install C
,执行后,依赖树就变成下面这样了。
proj 1.0.0
A 1.1.0
B 1.3.0
然后项目编译时就失败了,或者编译成功,但在浏览器中运行出错了,悲剧。
怎么办?还好查到了npmjs.com官方针对这个问题的说明,详见这里
npm shrinkwrap
的作用就是以项目为根,将项目依赖树上所有第三方库版本固定。 使用上还是比较简单的,就是执行npm shrinkwrap
命令,就会在package.json旁边上一个npm-shrinkwrap.json
,以后再执行npm install
,就会安装npm-shrinkwrap.json
里描述的确切版本。
不过这里还有一个小坑,官方文档里说明如下:
1 |
Since npm shrinkwrap is intended to lock down your dependencies for production use, devDependencies will not be included unless you explicitly set the --dev flag when you run npm shrinkwrap. |
---|
也就是默认不会锁定devDependencies
的版本,除非执行npm shrinkwrap
带上--dev
参数。我建议执行npm shrinkwrap
还是带上--dev
参数,否则很有可能某天一个开发依赖库版本小升个版本号,你的项目又悲剧了。
- go-nsq使用简述
- hdu---(4515)小Q系列故事——世界上最遥远的距离(模拟题)
- 利用sys schema解决一次诡异的语句hang问题
- hdu----(4513)吉哥系列故事——完美队形II(manacher(最长回文串算法))
- 学习manacher(最长公共回文串算法)
- Apache Spark 2.3 加入支持Native Kubernetes及新特性文档下载
- Oracle 12c 多租户专题|隔离PDB的磁盘IO
- golang 裸写一个pool池控制协程的大小
- 2014---多校训练2(ZCC Loves Codefires)
- 完整的golang 多协程+信道 任务处理示例
- 2014---多校训练一(A Couple doubi)
- hdu----(2586)How far away ?(DFS/LCA/RMQ)
- Golang控制goroutine的启动与关闭
- spring-boot-starter-swagger迎新伙伴支持,加速更新进度(1.3.0.RELEASE)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法