为何Node.js v16未将文件视为独立模块?版本差异疑问
Node.js v16下顶级await报错的原因与解决办法
Node.js v18官方文档说明“每个文件都被视为独立模块”,但在v16环境运行以下代码时,会触发报错:SyntaxError: await is only valid in async functions and the top level bodies of modules。
涉及代码
init.js
module.exports.TESTING = (process.argv[2] == 'test'); async function init() { let ss = require('./safestore.js'); let p = await ss.safestore.read(); return p; } await init();
it.js
require('./init.js');
执行命令 node it.js test 会触发上述报错,将init.js最后一行改为(async () => { await init(); })();则可正常运行。
原因解析
核心是Node.js v16与v18的模块机制差异:
- Node.js v18默认将.js文件识别为ES模块,天然支持顶级await(模块顶层直接使用await);
- v16中,.js文件默认是CommonJS模块,CommonJS模块不支持顶级await,只有明确声明为ES模块的文件(比如后缀改为.mjs,或在项目根目录package.json中设置
"type": "module")才能使用顶级await; - 用
require()加载init.js属于CommonJS加载方式,此时init.js会被当作CommonJS模块处理,顶层的await init()不符合语法规范; - 改成async立即执行函数能运行,是因为把await放在了合法的async函数作用域内,这在CommonJS模块中是允许的。
误区纠正
有人认为这是.js与.mjs后缀的差异,但本质并非如此——关键在于Node.js版本对模块默认处理逻辑的调整,v18改变了默认行为,而v16仍沿用旧规则。
内容的提问来源于stack exchange,提问作者Dave Scotese
相关产品推荐
相关产品推荐

