使用Webpack构建Node.js项目时遇await关键字报错求助
解决Webpack构建ESM项目时顶层await报错的问题
问题核心
你的Node.js ESM项目中使用了顶层await(直接在模块顶级作用域用await),Node.js本身支持这个语法,但Webpack构建时抛出Cannot use keyword 'await' outside an async function错误,且@babel/plugin-transform-runtime未解决问题。
解决方案
1. 让Babel识别顶层await语法
@babel/env预设默认不支持顶层await语法,需要显式添加语法支持插件。修改webpack.config.production.cjs中babel-loader的配置:
module.exports = { // ...其他配置 module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', options: { babelrc: false, presets: ['@babel/env'], plugins: [ '@babel/plugin-syntax-top-level-await', // 新增:支持顶层await语法 [ '@babel/plugin-transform-runtime', { regenerator: true, }, ], ], }, }, ], }, ], }, // ...其他配置 };
2. 开启Webpack的顶层await实验特性
Webpack 5+支持顶层await,但默认未开启,需在配置中添加实验性配置:
module.exports = { // ...其他配置 experiments: { topLevelAwait: true, // 开启顶层await支持 }, // ...其他配置 };
3. 优化冗余的异步代码(可选)
你的代码中存在不必要的Promise嵌套,map中的async函数本身已返回Promise,无需再包裹new Promise,简化后代码更简洁:
import { readdirSync } from 'fs'; import { fileURLToPath } from 'url'; import { parse as parsePath, dirname } from 'path'; const modules = await Promise.all( readdirSync(dirname(fileURLToPath(import.meta.url))).map(async (e) => { const pinfo = parsePath(e); if (pinfo.name !== 'index' && pinfo.name !== 'references') { return (await import(`./${pinfo.base}`)).default; } return {}; }) );
为什么之前的插件无效?
@babel/plugin-transform-runtime仅负责编译async/await为兼容代码,但不处理顶层await这个语法本身。必须配合@babel/plugin-syntax-top-level-await让Babel识别该语法,同时Webpack需开启实验特性才能正确打包使用顶层await的模块。
内容的提问来源于stack exchange,提问作者Ngọc Nguyễn
相关产品推荐
相关产品推荐

