Webpack5 踩坑之(html-webpack-plugin)

本文记录了作者在使用Webpack5时遇到与html-webpack-plugin不兼容的问题,详细分析了问题的原因,即Webpack5.22.0版本中html-webpack-plugin返回值的变化。为了解决这个问题,作者提出了两种解决方案:一是将html-webpack-plugin版本降级,二是直接修改本地源码。在社区分享解决方案后,得到了积极的反馈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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.
  
  - index.js:339 HtmlWebpackPlugin.evaluateCompilationResult
    [vue3-demo]/[html-webpack-plugin]/index.js:339:24
  
  - index.js:243 
    [vue3-demo]/[html-webpack-plugin]/index.js:243:22
  
  - task_queues.js:93 processTicksAndRejections
    internal/process/task_queues.js:93:5
  
  - async Promise.all
  
  - async Promise.all

起因

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

在这里插入图片描述

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.
  
  - index.js:339 HtmlWebpackPlugin.evaluateCompilationResult
    [vue3-demo]/[html-webpack-plugin]/index.js:339:24
  
  - index.js:243 
    [vue3-demo]/[html-webpack-plugin]/index.js:243:22
  
  - task_queues.js:93 processTicksAndRejections
    internal/process/task_queues.js:93:5
  
  - async Promise.all
  
  - 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 行:

...
	result.add(
				`${accessWithInit(
					fullNameResolved,
					this._getPrefix(compilation).length,
					false
				)} = __webpack_exports__${exportAccess};\n`
			);
...

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

render(source, { chunk }, { options, compilation }) {
		...
			source = new ConcatSource(`${this.declare} ${base};\n`, source);
}

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

// let source = `var HTML_WEBPACK_PLUGIN_RESULT;HTML_WEBPACK_PLUGIN_RESULT="hello"`; // webpack 5.22.0 以下版本
let source = `var HTML_WEBPACK_PLUGIN_RESULT;(function(){HTML_WEBPACK_PLUGIN_RESULT="hello"})()`; // webpack 5.22.0 版本
const vm = require("vm");
const vmContext = vm.createContext({ HTML_WEBPACK_PLUGIN: true, require: require, module, console: console ,...global});
const vmScript = new vm.Script(source);
// Evaluate code and cast to string
let newSource;
try {
    newSource = vmScript.runInContext(vmContext);
} catch (e) {
    return Promise.reject(e);
}
console.log(newSource);

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

undefined

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

hello

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

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

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

// let source = `var HTML_WEBPACK_PLUGIN_RESULT;HTML_WEBPACK_PLUGIN_RESULT="hello"`; // webpack 5.22.0 以下版本
let source = `var HTML_WEBPACK_PLUGIN_RESULT;(function(){HTML_WEBPACK_PLUGIN_RESULT="hello"})()`; // webpack 5.22.0 版本
const vm = require("vm");
const vmContext = vm.createContext({ HTML_WEBPACK_PLUGIN: true, require: require, module, console: console ,...global});
const vmScript = new vm.Script(source);
// Evaluate code and cast to string
let newSource;
try {
    vmScript.runInContext(vmContext);
} catch (e) {
    return Promise.reject(e);
}
newSource = vmContext.HTML_WEBPACK_PLUGIN_RESULT;
console.log(newSource);

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

newSource = vmContext.HTML_WEBPACK_PLUGIN_RESULT;

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

解决方法

  1. 对项目的 webpack 版本进行降级,降到 v5.22.0 以下。

  2. 修改本地的 html-webpack-plugin 源码,找到你本地的 xxx/node_modules/html-webpack-plugin/index.js325 行:

     // Evaluate code and cast to string
        let newSource;
        try {
          // fix issues: https://github.com/jantimon/html-webpack-plugin/issues/1603
          // newSource = vmScript.runInContext(vmContext);
          vmScript.runInContext(vmContext);
        } catch (e) {
          return Promise.reject(e);
        }
        // see issues: https://github.com/jantimon/html-webpack-plugin/issues/1603
        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 项目。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值