我是如何调试 Webpack 运行问题的

全文 3000 字,欢迎点赞转发

事情是这样的,某天有个小伙伴问我:为啥我的 webpack 运行完看不到我写的页面,而是:

我是如何调试 Webpack 运行问题的_第1张图片

嗯?文件列表页?好吧,这种情况我似乎没遇到过,一下子没法给出答案,只能要来关键代码:

我是如何调试 Webpack 运行问题的_第2张图片

重点看看 webpack.config.js 配置,用到 devServer + HMR 功能,其中:

  • Webpack 版本为 5.37.0
  • webpack-dev-server 版本为 3.11.2

看了半天,没问题呀,给了几个纸糊的建议还是解决不了问题,刚好在开会这事就暂且放下了。过了一会,小伙伴兴冲冲跑过来跟我说经过一番盲猜,问题被解决了:

  • output.publicPath = '/' 时一切正常
  • output.publicPath = './' 时出错,返回文件列表页

啊?这玩意还会影响 devServer 的效果,直觉告诉我不应该啊。

我是如何调试 Webpack 运行问题的_第3张图片

emmm,成功勾起我的好奇心了,虽然写过一些 Webpack 源码分析的文章,但 webpack-dev-server 确实不在我的知识范围,好在我有秘籍《如何阅读源码 —— 以 Vetur 为例》,是时候展示真正的技术了!

第一步:定义问题

先复盘一下问题发生的过程:

  • webpack.config.js 同时配置了 ouput.publicPathdevServer
  • 运行 npx webpack serve 启动开发服务器
  • 浏览器访问 http://localhost:9000 没有按预期返回用户代码,而是返回了文件列表页面;但如果恢复 output.publicPath 的默认配置,一切如常

讲道理, ouput.publicPath 应该只是影响了最终产物引用的路径,试试命令行工具运行 curl 检测首页返回的内容:

我是如何调试 Webpack 运行问题的_第4张图片

Tips:有时候可以试试绕过浏览器的复杂逻辑,用最简单的工具验证 http 请求返回的内容。

可以看到,请求 http://localhost:9000 地址返回一大串 html 代码,且页面的 title 为 listing directory —— 也就是我们看到的文件列表页面:

我是如何调试 Webpack 运行问题的_第5张图片

虽然不知道这是在那一层生成的,但可以肯定绝对不是我写的,而且这是在 HTTP 层面发生的。

所以问题的核心就是:为何 Webpack 的 output.publicPath 会影响 webpack-dev-server 的运行效果

第二步:回顾背景

带着问题我又 review 了一遍 Webpack 官方文档。

publicPath 配置

首先 output.publicPath 是这么描述的:

This is an important option when using on-demand-loading or loading external resources like images, files, etc. If an incorrect value is specified you'll receive 404 errors while loading these resources.

大意就是,这是一个控制按需加载或资源文件加载的选项,如果对应的路径资源加载失败时会返回 404。

嗐,其实这段描述就非常不明所以了,简单理解 output.publicPath 会改变产物资源在 html 文件的路径,比如说 Webpack 编译完生成了 bundle.js 文件,默认情况下写到 html 的路径是: