前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用npm版本锁定的必要性

使用npm版本锁定的必要性

作者头像
epoos
发布2022-06-06 15:43:14
1.1K0
发布2022-06-06 15:43:14
举报
文章被收录于专栏:epoos.comepoos.com

事情的背景

我司的项目基本上都是后端java,前端随意。 前端什么技术都有,react、vue、jquery、regular、seajs… 好在构建工具不复杂,也就是用的gulp + webpack 其实,还算是比较灵活了,虽然没有用nodejs,但是java的ftl模板也足够支持前后端分离了。

发布是走的公司运维开发的发布系统,由于历史原因,发布构建的时候,每修改一次代码需要分两步发版,分别是: 前端发布:webpack+gulp构建,然后发前端静态资源到cdn 后端发布:webpack+gulp构建,然后发ftl文件以及java文件到源站。

并且两次发布所在的目录是不同的,因此也就需要执行npm install - npm build多次,也就意味着有两套node_modules

问题

当然了,还是历史原因,我们项目中有部分代码是在本地构建之后提交到版本库的。 而本次我的任务就是解决历史问题,然后将代码本地构建改为发版构建。

于是,问题来了。

我在将本地构建改为发布构建的时候突然发现某个js资源404了,经检查,原来是两次构建的文件hash值不一样。 也就是说,前端发布的时候和后端发布的时候两次编译出来的文件hash值不一样。

经过多次测试,发现: 我本地是好的,多次构建都是完全一样的,哪怕是删除了package.json、node_modules 而同样的某一台构建服务器上却是两次构建不一样,并且两次和我本机的构建hash也不一样。 另外其它的构建服务器上却是两次构建一样,并且两次和我本机的构建hash不一样。

分析

hash值是根据文件内容算出来的,理论上来说不一样的文件内容计算出来的结果一定是不一样的。 因此,一定是编译出来的文件某个地方不一样才导致的hash不同。

既然有了猜想,便去验证一番,经过一番折腾终于拿到了构建机器两次构建之后的源码 后经过一番对比,发现文件大部分内容都是一样的,只有极少部分变量名不同 其中有一个地方引起了我的注意,那就是某个es6转换成es5代码之后的某个方法有些异常,虽然结果一样,但是语法、方法结构却不一样

难道是babel? 同样版本的构建为什么会出现不一样的文件?

等等,同样的构建?突然想到,npm的package.json版本管理的原理。

我们的package.json文件都是用的上尖括号(范版本)

代码语言:javascript
复制
"dependencies": {
  "vue": "^2.4.2",
  "vue-resource": "^1.3.4",
  "vue-router": "^2.7.0",
  "vuex": "^3.0.1"
},

尖括号的意思是,匹配所有的次要版本,也就是说:

代码语言:javascript
复制
如果当前配置的是 ^1.1.1
当依赖包最新版本为 1.x.x的时候,下次npm install就会自动安装最新的版本。
但是会忽略 2.0.0及以上版本

除此之外还有一种匹配模式是波浪号,匹配第二次要的版本

代码语言:javascript
复制
"dependencies": {
  "vue": "~2.4.2",
  "vue-resource": "~1.3.4",
  "vue-router": "~2.7.0",
  "vuex": "~3.0.1"
},

比如

代码语言:javascript
复制
如果~1.1.1,当最新版本为 1.1.x的时候,下次npm install就会自动更新最新的版本
但是会忽略 2.2.0及以上版本

莫非是因为babel升级了一个小版本?而我们的node_module有的更新了,有的没有更新? 这个还真的很有可能,因为我们的构建机器上的依赖包是优先缓存的,而之前为了做实验我做了清缓存的操作,有可能是有的更新了缓存,有的却没有更新。

因为有了这个猜想,便去验证一番,如果是安装包的问题,那么是不是说只需要做到几次安装的node_module下的依赖包版本一致,就能解决这个问题了呢?

实践

解决版本锁定也很简单,加个npm-lock就可以了 但是npm本身支持lock是在5.0.0以上的,而我们构建服务器因为nodejs版本还是6.x.x,因此对应npm可能不支持npm-lock 好在我们发版构建工具支持yarn,yarn本身就支持yarn-lock,只需要把yarn-lock提交上去就可以了(之前由于历史原因,将yarn-lock忽略掉了)

于是,我把yarn-lock提交上去之后,咦?好了! 嗯,问题就这样好了,两次构建出来的hash值不但一致了,就连和我本地构建出来的文件hash也是一致的了。

至此时,本人内心很平静,毫无波澜。

总结与分析

很明显,问题就是出在依赖包,因为使用了范版本,不同的机器安装的包是不一样的,那么构建出来的代码(尤其是压缩、babel等语法解析作用的包处理之后的代码)是非常可能不一样的。

npm早期版本其实也有解决这个问题的方案,那就是 npm shrinkwrap ,这个也是用作版本锁定的,并且到目前为止也是兼容的,其优先级高于npm-lock 当然,最简单的还是使用yarn,至少可以少跑一个命令。

以后为了解决各种奇怪的编译问题,还是做好版本锁定的好。

补充

npm安装包加lock可以提升安全性,更好的让开发人员对安装包进行代码review,减少恶意安装包肆意更新带来的安全隐患

— 全文完 —

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-05-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 事情的背景
  • 问题
  • 分析
  • 实践
  • 总结与分析
  • 补充
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档