6

【包管理器】一个由第三方包管理器与npm冲突导致的bug

 3 years ago
source link: https://blog.vadxq.com/article/other-package-manage-error/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

【包管理器】一个由第三方包管理器与npm冲突导致的bug

这是一个神奇的bug,也是一个花费时间的bug哈哈哈。当遇到这种类型的bug确实会出现挺难下手的尴尬之处。

下面便是我对这个bug的折磨历程,对,我对它的折磨!

项目背景与问题分析

这是一个老项目,可能由于以前跳版本出现问题,前辈固定了版本,使用的是npm shrinkwrap来固定版本,但由于前辈使用的是cnpm,所以当是形成的依赖包名字是下划线开头的。当后人使用npm安装的时候,便出现了这样的问题:

npm ERR! Invalid package name "_@[email protected]@@types": name cannot start with an underscore; name can only contain URL-friendly characters

报错原因如字面意思,包名不够友好。所以问题在于包的问题

尝试使用固定依赖包解决问题

当发现这一步的时候,便开始了npm更多可能性的探索历程。npm-shrinkwrap.json文件,我也是第一次见,现在一般用lock用的多些。下面是他们的区别。

  • npm-shrinkwrap.json与npm v2/3/4或者是后面的兼容,而package-lock.json仅可在npm v5+版本可用
  • package-lock.json不在文件的根目录将会被忽略,但须依赖shrinkwrap文件
  • npm-shrinkwrap.json其他人安装依赖必须是一样的,而package-lock.json准确记录您安装的依赖项的版本,其他人则可以安装规定的范围内兼容的依赖项的任何版本

处理方法是使用很笨的方法,将包全部提取出来固定的版本,然后将npm-shrinkwrap.jsonpackage-lock.json文件删除,手动npm i,再将新生成的package-lock.json重新生成一份npm-shrinkwrap.json

结果:解决的大部分安装包问题,但是有一个包出现错误。那就是vue-echarts。报错信息如下:Uncaught TypeError: Cannot use 'in' operator to search for 'default' in undefined

尝试使用webpack解决问题

出现了如上结果,TypeError,问题错误显示错在vue-echarts上,于是乎,google搜索了以下问题,也去github issues搜索了遍,包的issue确实出现过问题,但是并没有什么解决方案。后来查找到了此条TypeError: Cannot use ‘in’ operator to search for ‘default’ in undefined #1407,问题提在了rollup上,看了下,好像是说是升级版本可用,同是打包工具,盲猜是不是因为webpack引入问题。于是乎便重新看了下webpack配置,看看引入vue-echarts的webpack有没有黑魔法。

      {
test: /\.js$/,
loader: 'babel-loader',
- include: [resolve('src'), resolve('test')]
+ include: [
+ resolve('src'),
+ resolve('test'),
+ resolve('node_modules/vue-echarts'),
+ ]
}

配置如同文档所写,也没啥大变化,也没啥特别之处,此方法pass。

尝试使用更改vue-echarts版本

我们项目目前使用的vue-echarts版本是v2.6.0版本,由于往后版本是跳大版本3.0.0,引入的Echarts也是大版本更新到
v4+,所以更新往上只尝试了一个版本,往下尝试了好几个版本,皆无功而返,没有任何用处。所以也就不再去比对新版本带来的特性会对现有的功能造成影响。

由于周五下午了,我们公司搬新大楼,收拾东西,也就没有再细究下去,心思也浮了。

尝试比对源码

当到了这一步的时候,已经周一了,收拾了下新公司楼层座位,便开始了上周的问题,开始静心分析源码。比对了vue-echarts的部分初始化问题,自己的推测大概问题出现在了初始化配置项的问题。于是乎在配置项分析了一会,修改配置,更改项目代码的配置项,发现也没甚问题。

后来觉得是不是vue的生命周期导致echarts初始化问题。修改后发现无效果。

后来干脆把npm下载的vue-echarts源码和cnpm下载可运行的vue-echarts包源码对比,不看不知道,一看哭笑不得。

请看如下图:

当时的心情就是想吐血!!!

所以问题出现在了cnpm居然跳版本安装了带有npm-shrinkwrap.json的项目的依赖!

知道问题所在,解决起来就简单了,将包版本更新至v3.1.3后,确实不会报那个错了。

但是会出现其他问题。原先引用的实例是直接挂在在根上,而今挂在VueECharts上,所以这里只要赋值多加个字段就好了。

分析第三方包管理原因

我对此的猜测是因为两种工具的模块机制不太一样。各位看官可以看看cnpm与npm的模块机制不一样的问题。目前网上还没有相关的讨论,只发现了一篇文章:为什么我从 Npm 到 Yarn 再到 Npm?,后面我会继续更新这篇文章具体探讨一下这一块的问题。个人觉得目前如果项目用的npm都是v6.0+版本的话,建议不要使用第三方包管理器了。

附带个人在项目中的解决方案,使用了黑魔法兼容两者的模块机制不同导致会出现的问题

import * as Echarts from 'vue-echarts'
// 由于旧版使用cnpm安装锁定包版本,但是cnpm将vue-echarts版本从2.6.0跳3.1.3版本,所以会出现用npm安装报错问题,现将版本切换至npm的3.1.3,兼容npm可用。还有个深层原因是因为引入模块的机制导致cnpm与npm差异。
if (Echarts) {
window.echarts = Echarts
if (Echarts.VueECharts) {
window.echarts = Echarts.VueECharts
}
} else {
window.echarts = null
}
// Echarts && Echarts.VueECharts ? window.echarts = Echarts.VueECharts : window.echarts = null

// window.echarts = Echarts.VueECharts
console.log(window.echarts)

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK