2021 開工第一天就給我個大大的驚喜。
起因
今天起了個大早障陶,懷著無比激動的心情來到了公司滋恬,一切還是跟往常一樣,當(dāng)我打開電腦并打開項目抱究,就出現(xiàn)了下面的場景了:
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
心態(tài)崩了呀恢氯,之前還是好好的,咋就涼了呢鼓寺?
經(jīng)過
找bug
的過程比較漫長勋拟,我就不在這里描述了~
原因
環(huán)境
- webpack:v5.22.0
- html-webpack-plugin:v4.5.1
由于 webpack5.22.0
版本中修改了 library
的生成方式,具體代碼在 webpack5.22.0
源碼文件 webpack/lib/library/AssignLibraryPlugin.js
第 279
行:
...
result.add(
`${accessWithInit(
fullNameResolved,
this._getPrefix(compilation).length,
false
)} = __webpack_exports__${exportAccess};\n`
);
...
跟 webpack5.22.0
源碼文件 webpack/lib/library/AssignLibraryPlugin.js
第 212
行:
render(source, { chunk }, { options, compilation }) {
...
source = new ConcatSource(`${this.declare} ${base};\n`, source);
}
這樣說可能有點抽象妈候,大家可以在 node
環(huán)境中運(yùn)行一下下面這段代碼:
// 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
插件敢靡,運(yùn)行后可以發(fā)現(xiàn)返回的是:
undefined
然后我們模擬一下 webpack 5.22.0
以下版本的 html-webpack-plugin
插件,運(yùn)行后可以發(fā)現(xiàn)返回的是:
hello
當(dāng)然苦银,我這只是模擬一下 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;
我們再次運(yùn)行后會發(fā)現(xiàn),代碼正常返回了 hello
字符串想括。
解決方法
對項目的
webpack
版本進(jìn)行降級柠辞,降到v5.22.0
以下。-
修改本地的
html-webpack-plugin
源碼主胧,找到你本地的xxx/node_modules/html-webpack-plugin/index.js
第325
行:// 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;
結(jié)果
首先肯定是不能去罵 webpack
叭首,畢竟別人是大哥大,他會說 “我是不會改的踪栋,你愛用不用”焙格,所以就只能委屈一下 html-webpack-plugin
了,于是我點開了html-webpack-plugin
在 github
的 issues
夷都,太哇塞了呀眷唉,已經(jīng)有很多人在討論了 Webpack v5.22.0` breaks HtmlWebpackLoader #1603。
于是我趕緊在底下貼上我的解決方案并附上(you can do this):
然后趕緊去給作者提個 pr
蹭個 contributor
,哈哈冬阳,畢竟別人是幾千 k 的 star 項目蛤虐。