blog
blog copied to clipboard
webpack 打包失败问题记录
今天发生了一个奇怪的事情
半个月之前已经上线没问题的一个工程,突然构建失败,看报错是 webpack 抛出来的,提示我没有传入有效的参数(或者 webpack.config.js 文件)
于是我把本地的 node 版本和 npm 版本降到了跟服务器一样的 6.9.2 和 3.10.9,删掉 node_modules 然后重新安装依赖,复现了这个错误。
为了定位这个问题
- 到 webpack 内部去调试,断点不好打,直接改 webpack 的代码加一下 console.log 这种东西,发现根本没有进去 webpack 的函数里面。
- webpack 是用 yargs 处理传入参数的,因为 webpack 可以不用配置文件,直接将需要的配置跟在 webpack 命令后面就可以运行了。发现在 yargs 阶段就报错了,相当于必填校验没过,进不去服务端。
- 手动改掉 yargs 的参数,把必填校验给去掉,成功进去打包
- 怀疑是 webpack 更新了,所以将 webpack 版本降下来了
- 并没有任何卵用,照样报错,去 github 上看了下 webpack 近期(半个月)并没有发版
- 这个时候感觉毫无头绪。。。
- 突然想到还有另外一个工程跟这个工程的配置几乎一样
- 去部署希望工程,发现希望工程竟然是好的!!!
- 检查希望工程的 package.json 发现 webpack 的版本是一致的
- 排除差异,对比十几个不一致的包,把不会引起错误的一些包给去掉,最后只有4个包版本不一致
- 由于排除差异的过程中会一直尝试打包,一直失败。这个过程得重新安装依赖,超级浪费时间
- 最后最后,排除到了问题所在,万万没想到是我出错工程里面依赖的一个 yargs 的版本用的
^10.0.3
- yargs 这个东西不可能影响打包的啊,这个只用于起工程,起 mock 的时候的一个小命令行工具,为什么会影响到 webpack 打包呢
- 调试了一下发现,webpack 自己也依赖 yargs ,但是依赖的版本是
^8.x
,然而 webpack 用的是我外面高版本的 yargs ,在他自己的 node_modules 里面连 yargs 这个包都没有下下来 - npm 更新到 5.2.0 就没有这个问题了,说到这里真的不得不吐槽一下我厂的生产测试环境,版本是真的低
- 仔细研究一下坑爹的 npm 包管理机制,由于 npm3.x 的文档已经找不到了,只能看看目前的版本是怎么做的
npm 打包机制
npm v2
如果我的项目依赖包A和包C,但是A依赖[email protected],C依赖[email protected],npm 会无脑的在依赖的A和C各自的 node_modules 里面再去下载各自依赖的包,那么是这样的
假如B依赖D,D又依赖E,不同的版本的依赖都不同,那么 node_modules 的层级会非常深
npm v3
像上面的那样肯定是有问题的,可以做一个简单的优化,把相同的依赖抽出来放在外面
现在有一个包[email protected]依赖包[email protected],那么 npm 在第一次去下载B的时候下载一个1.0版本的 B 放在外面
如果还有另外的包也依赖[email protected]的话就不需要额外再去下载了,假如另外的包C依赖的是[email protected]那么没办法只能再去下载一个[email protected]放在B自己的node_modules 里面去
npm v3 Duplication
在上面的基础上继续,如果有多个包依赖[email protected],那么由于[email protected]在外面,只能多个包都在自己的 node_modules 里面下载一个 [email protected]
这个时候如果有一个E的包依赖[email protected],那么就不需要再去下载了,用外面的包就可以了
假如A这个包依赖的B的版本更新成 2.0 了,那么A也得在他自己的 node_modules 里面下载一个 2.0 的包
假如这个时候E也更新成了依赖[email protected],那么没人依赖[email protected]了,但是因为[email protected]还是在外面,所以还是只能在自己的 node_modules 里面下载一个包
但是这样明显就有问题了,我们可以用
npm dedupe
命令让 npm 重新调整一下
总结
npm 安装的时候感觉还是特别的死,根据包的顺序来做一个简单的处理,第一次加载某个依赖的时候会放外面,后面如果有依赖其他版本,无论依赖的次数是否比第一次依赖的次数多,都还是在自己的 node_modules 里面重新再安装。。感觉还是比较笨,还有很大的提升空间