npm与一次版本更新事故
|最近Element-ui
发布了2.0的版本,打算将之前为项目搭的后台管理系统进行升级,由于之前这方面的经验比较少,导致出现了一些比较蛋疼的问题,甚至导致本地的开发环境接近崩溃,于是记录下来,并整理的与npm相关的一些问题。
<!--more-->
参考:
1. 起因
事情的经过是这样的:
去官网查文档的时候提示发布了2.0正式版,发现添加了一些比较有用的功能(比如嵌套dialog、自定义icon以及组件样式更新等),于是在本地开了一个分支update_ele
。
由于node_modules
一般会放在.gitignore
中忽略提交,因此对于这种需要进行依赖库升级的分支,必须在切换分支时手动更新依赖库。(实际上克隆仓库然后单独更新应该是更明智的做法,但是当时脑子抽了,导致了后面的一系列问题)
事实上我对于npm也只停留在初级使用的阶段,所以相关的更新操作等都是边查文档边进行的。
然后就开始折腾了。
2. npm安装依赖包
2.1. 安装细节
通常在开发过程中,我们会按需安装相关的包,并且可以通过save
和save-dev
连个参数将该包添加进package.json
,方便多人协作开发。他们的区别在于:
save
将包添加进dependencies
字段下,对应的运行时依赖库,即项目本身依赖的库,比如vue,jQuery等,简写方式-S
save-dev
将包添加进devDependencies
下,对应的时开发时依赖库,比如gulp
等,简写方式-D
然而打开package.json
我们会发现,大部分依赖包前面的都会有^
或~
的符号,他们的意思是,在使用npm install
命令时:
^
会匹配最新的大版本依赖包,比如^1.2.3会匹配所有1.x.x的包,包括1.3.0,但是不包括2.0.0~
会匹配最近的小版本依赖包,比如~1.2.3会匹配所有1.2.x版本,但是不包括1.3.0- 如果没有任何前置修饰符,则表示安装对应制定的版本号
详情可见文档。默认使用-S
或-D
安装时会自动添加^
修饰符,因此在某些时候会造成版本的不兼容(所以说发版本包的时候版本号不能乱取啊)
2.2. 查看已安装的版本
通过上面我们知道package.json
中的版本号,如果有前缀修饰符,则不能代表当前项目中具体使用的版本,如果我们需要查看具体的版本号,可以使用
npm list --depth=0
对应包名后面的@x.x.x
即为当前使用的版本号,由npm自动帮助我们管理版本依赖。
2.3. 安装指定版本
# 查看对应包的所有可用版本
npm view element-ui versions
# 安装2.0.0
npm i element-ui@2.0.0 -S
2.4. 锁定版本
npm install
会根据修饰符更新版本带来的一个问题就是版本兼容,如果我们自己的项目依赖于某个包的某个版本的特性,在该依赖包升级之后,向后兼容的代价也许会比较大。因此我们可能需要某种锁定包版本的问题。
一种方法是使用去除package.json
的前缀修饰符,仅保留精确的版本号。
另一种方法是package-lock.json。
升级到node8.0以后,npm也会升级到npm5,在之前的项目中使用npm进行安装的时候,会发现多了一个package-lock.json
的文件,
- 该文件中已经记录了整个
node_modules
文件夹的树状结构,甚至连模块的下载地址都记录了,再重新安装的时候只需要直接下载文件即可。 - 当存在
package-lock.json
的文件时,使用npm install
将不会再根据前缀修饰符更新模块(准确的说不会根据package.json
文件安装模块),更新模块只能使用npm install xxx@v.v.v
这样的形式进行,此时会自动更新package-lock.json
的信息。
通过package-lock
的文件可以保证项目保持一系列固定的依赖版本,而不同担心依赖库升级导致的版本冲突。
在之前使用过的PHP包管理工具composer
中貌似也有对应的用于锁定版本的处理机制,即composer-lock
文件。
2.5. 镜像
国内使用npm安装包比较慢,一般会使用镜像比如淘宝镜像,这里存在的坑是:尽量使用修改镜像仓库地址的方式,而不是使用cnpm
npm config set registry http://registry.npm.taobao.org/
因为早前使用cnpm
遇见了很多依赖库版本不一致产生的冲突问题,比如
3. 版本升级
上面整理了npm使用过程中遇见的一些知识点。接下来就是回顾这次element-ui
版本升级中遇见的一些问题。这应该也是大部分依赖库的升级过程中可能会遇到的问题。
3.1. 接口兼容
类似于1.x
到2.x
之类的大版本更新,相关的接口改动可能会比较多,因此动手之前记得先查看官方的更新日志,比如releases。这样对于可能产生冲突的地方会有大致的了解。
比如element-ui
2.0的版本对图标、dialog等组件进行了调整,在控制台也可以看见相关的警告(侧面说明选择一个稳定的库是多么重要)
3.2. 版本兼容
当我在新分支安装了2.0,更新了新接口之后,切换到旧分支时,需要重新安装对应版本的element-ui
,通过查看package.json
中的分支
"dependencies": {
"element-ui": "^1.2.9",
}
然后手动安装了npm i element-ui@1.2.9 -S
,然后发现样式不对~想必您已经知道原因了:前缀修饰符的存在导致package.json
中的版本不一定正确。
然而当时我并不知道这个原因,然后又升级了vue
的版本,接着vue-loader
等一系列脚手架依赖库都报出了版本不对的错误,整个人都懵逼了。最后折腾了半天,删除了node_modules
文件重新安装,最终可以跑起来了,然而我到现在都还不知道有没有引入新的BUG。
正如前面提到的,针对项目依赖库的升级,更明智的选择应当是克隆一个本地仓库然后独立进行开发,由于.gitignore
的存在,多个分支会公用这部分本地文件,而来回的改动肯定会比较麻烦。
4. 小结
git
用的不是很熟,npm
用的也不熟,所以导致了这次事故的发生,幸好只是本地的开发环境崩掉了,不然后果还是比较严重的。
另外关于yarn
基本上也没有接触过,有空可以试试。