electron项目升级了webpack5,项目跑起来发现报错,regeneratorruntime is not defined,项目无法正常运行 😂
报错原因
这个报错是由于 async function 语法糖被 babel 转译之后使用了 regeneratorRuntime
这个变量,但是这个变量在最终的代码里未定义造成的报错。
情景复现
我们新建一个文件,使用 async 语法来编写代码
// index.js
async function foo() {
const ret = await Promise.resolve(2);
console.log(ret);
}
foo();
配置 webpack.config.js
// webpack.config.js
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.bundle.js',
}
};
运行 webpack 后打包出的结果如下
!async function () { const o = await Promise.resolve(2); console.log(o) }();
为了兼容低版本浏览器,我们再引入 babel
module.exports = {
...
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
}
};
配置 .babelrc
如下
{
"presets": [
[
"@babel/preset-env"
]
]
}
打包的结果如下
!function(){function n(n,e,r,t,o,i,u){try{var c=n[i](u),a=c.value}catch(n){return void r(n)}c.done?e(a):Promise.resolve(a).then(t,o)}function e(e){return function(){var r=this,t=arguments;return new Promise((function(o,i){var u=e.apply(r,t);function c(e){n(u,o,i,c,a,"next",e)}function a(e){n(u,o,i,c,a,"throw",e)}c(void 0)}))}}function r(){return(r=e(regeneratorRuntime.mark((function n(){var e;return regeneratorRuntime.wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return n.next=2,Promise.resolve(2);case 2:e=n.sent,console.log(e);case 4:case"end":return n.stop()}}),n)})))).apply(this,arguments)}!function(){r.apply(this,arguments)}()}();
运行一下打包 index.bundle.js 文件,发现报错了,错误如下图
因为 babel 在转 async 语法的时候,使用 regeneratorRuntime
这个变量。然后这个变量未声明,所以报错了。
解决办法
1. 配置 @babel/preset-env
的 targets
选项
如果我们确定代码运行在兼容 async 语法的环境下,可以配置 node 的版本,这样 babel 在转换的时候就不会去处理 async 语法的代码
{
"presets": [
[
"@babel/preset-env", {
"targets": {
"node": "15.4"
}
}
]
]
}
结果等同于上面不配置 babel 的情况
!async function () { const o = await Promise.resolve(2); console.log(o) }();
2. 配置 @babel/plugin-transform-runtime
(推荐)
{
"presets": ["@babel/preset-env"],
"plugins": [
"@babel/plugin-transform-runtime"
]
}
3. 配置 @babel/preset-env
的 useBuiltIns
(不推荐)
如果使用 usage
或者 entry
,将会使用 core-js
模块来处理,默认使用 2.0 版本,我们这里安装3.0 npm i core-js@3.17.3
,然后手动声明 corejs
版本
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": "3.17.3"
}
]
]
}
使用 useBuiltIns 可能会修改全局变量或者全局对象的原型链,如果多个库同时修改同一变量的情况下就会导致难以跟踪的问题 https://github.com/babel/babel/issues/10271#issuecomment-5283795