Webpack5 踩坑之(html-webpack-plugin)

秒速五厘米 2022-10-30 07:27 355阅读 0赞

2021 开工第一天就给我个大大的惊喜。

  1. ERROR in Error: The loader "/home/project/vue3-demo/node_modules/html-webpack-plugin/lib/loader.js!/home/project/vue3-demo/public/index.html" didn't return html.
  2. - index.js:339 HtmlWebpackPlugin.evaluateCompilationResult
  3. [vue3-demo]/[html-webpack-plugin]/index.js:339:24
  4. - index.js:243
  5. [vue3-demo]/[html-webpack-plugin]/index.js:243:22
  6. - task_queues.js:93 processTicksAndRejections
  7. internal/process/task_queues.js:93:5
  8. - async Promise.all
  9. - async Promise.all

起因

今天起了个大早,怀着无比激动的心情来到了公司,一切还是跟往常一样,当我打开电脑并打开项目,就出现了下面的场景了:

在这里插入图片描述

  1. ERROR in Error: The loader "/home/project/vue3-demo/node_modules/html-webpack-plugin/lib/loader.js!/home/project/vue3-demo/public/index.html" didn't return html.
  2. - index.js:339 HtmlWebpackPlugin.evaluateCompilationResult
  3. [vue3-demo]/[html-webpack-plugin]/index.js:339:24
  4. - index.js:243
  5. [vue3-demo]/[html-webpack-plugin]/index.js:243:22
  6. - task_queues.js:93 processTicksAndRejections
  7. internal/process/task_queues.js:93:5
  8. - async Promise.all
  9. - async Promise.all

心态崩了呀,之前还是好好的,咋就凉了呢?

经过

bug 的过程比较漫长,我就不在这里描述了~

原因

环境

  • webpack:v5.22.0
  • html-webpack-plugin:v4.5.1

由于 webpack5.22.0 版本中修改了 library 的生成方式,具体代码在 webpack5.22.0 源码文件 webpack/lib/library/AssignLibraryPlugin.js279 行:

  1. ...
  2. result.add(
  3. `${
  4. accessWithInit(
  5. fullNameResolved,
  6. this._getPrefix(compilation).length,
  7. false
  8. )} = __webpack_exports__${
  9. exportAccess};\n`
  10. );
  11. ...

webpack5.22.0 源码文件 webpack/lib/library/AssignLibraryPlugin.js212 行:

  1. render(source, {
  2. chunk }, {
  3. options, compilation }) {
  4. ...
  5. source = new ConcatSource(`${
  6. this.declare} ${
  7. base};\n`, source);
  8. }

这样说可能有点抽象,大家可以在 node 环境中运行一下下面这段代码:

  1. // let source = `var HTML_WEBPACK_PLUGIN_RESULT;HTML_WEBPACK_PLUGIN_RESULT="hello"`; // webpack 5.22.0 以下版本
  2. let source = `var HTML_WEBPACK_PLUGIN_RESULT;(function(){HTML_WEBPACK_PLUGIN_RESULT="hello"})()`; // webpack 5.22.0 版本
  3. const vm = require("vm");
  4. const vmContext = vm.createContext({
  5. HTML_WEBPACK_PLUGIN: true, require: require, module, console: console ,...global});
  6. const vmScript = new vm.Script(source);
  7. // Evaluate code and cast to string
  8. let newSource;
  9. try {
  10. newSource = vmScript.runInContext(vmContext);
  11. } catch (e) {
  12. return Promise.reject(e);
  13. }
  14. console.log(newSource);

这是模拟的 webpack 5.22.0 版本下的 html-webpack-plugin 插件,运行后可以发现返回的是:

  1. undefined

然后我们模拟一下 webpack 5.22.0 以下版本的 html-webpack-plugin 插件,运行后可以发现返回的是:

  1. hello

当然,我这只是模拟一下 html-webpack-plugin 插件,真正返回的可不是 hello 字符串。

报错的原因正是因为 webpack 5.22.0 版本下的 html-webpack-plugin 插件返回的是 undifined 而不是 hello

我们可以试着改一下上面的 webpack 5.22.0 版本下的 html-webpack-plugin 插件代码:

  1. // let source = `var HTML_WEBPACK_PLUGIN_RESULT;HTML_WEBPACK_PLUGIN_RESULT="hello"`; // webpack 5.22.0 以下版本
  2. let source = `var HTML_WEBPACK_PLUGIN_RESULT;(function(){HTML_WEBPACK_PLUGIN_RESULT="hello"})()`; // webpack 5.22.0 版本
  3. const vm = require("vm");
  4. const vmContext = vm.createContext({
  5. HTML_WEBPACK_PLUGIN: true, require: require, module, console: console ,...global});
  6. const vmScript = new vm.Script(source);
  7. // Evaluate code and cast to string
  8. let newSource;
  9. try {
  10. vmScript.runInContext(vmContext);
  11. } catch (e) {
  12. return Promise.reject(e);
  13. }
  14. newSource = vmContext.HTML_WEBPACK_PLUGIN_RESULT;
  15. console.log(newSource);

可以看到,我们加了下面这一行代码:

  1. newSource = vmContext.HTML_WEBPACK_PLUGIN_RESULT;

我们再次运行后会发现,代码正常返回了 hello 字符串。

解决方法

  1. 对项目的 webpack 版本进行降级,降到 v5.22.0 以下。
  2. 修改本地的 html-webpack-plugin 源码,找到你本地的 xxx/node_modules/html-webpack-plugin/index.js325 行:

    1. // Evaluate code and cast to string
    2. let newSource;
    3. try {
    4. // fix issues: https://github.com/jantimon/html-webpack-plugin/issues/1603
    5. // newSource = vmScript.runInContext(vmContext);
    6. vmScript.runInContext(vmContext);
    7. } catch (e) {
    8. return Promise.reject(e);
    9. }
    10. // see issues: https://github.com/jantimon/html-webpack-plugin/issues/1603
    11. newSource = vmContext.HTML_WEBPACK_PLUGIN_RESULT;

结果

首先肯定是不能去骂 webpack,毕竟别人是大哥大,他会说 “我是不会改的,你爱用不用”,所以就只能委屈一下 html-webpack-plugin 了,于是我点开了html-webpack-plugingithubissues ,太哇塞了呀,已经有很多人在讨论了 Webpack v5.22.0` breaks HtmlWebpackLoader #1603。

于是我赶紧在底下贴上我的解决方案并附上(you can do this):
在这里插入图片描述
然后赶紧去给作者提个 pr 蹭个 contributor,哈哈,毕竟别人是几千 k 的 star 项目。

发表评论

表情:
评论列表 (有 0 条评论,355人围观)

还没有评论,来说两句吧...

相关阅读

    相关 h5记录

    1. `IOS` 上滑底部会漏出白边,效果不佳,故需要在 `IOS` 中有蒙层出现时禁止上滑,从而能够提高用户体验性。通过给 `body` 标签加样式 `style="ove

    相关 日志elasticSearch

    前言 > 上周六马上就下班了,正兴高采烈的想着下班吃什么呢!突然QA找到我,说我们的DB与es无法同步数据了,真是令人头皮发秃,好不容易休一天,啊啊啊,难受呀,没办法,还