GitHub Actions运行Puppeteer报ES模块作用域__dirname未定义错误
你手动定义__dirname不生效的核心原因是ESM的静态import存在变量提升:所有顶层静态导入的模块会优先加载执行,你写在import puppeteer之前的赋值代码,实际执行顺序晚于puppeteer内部代码的执行,因此puppeteer运行时还是拿不到__dirname。
方案1:修改ncc编译参数输出CommonJS产物(最稳妥)
直接调整ncc打包命令,添加--cjs参数强制输出CommonJS格式,从根源规避ESM和CommonJS的变量兼容问题:
ncc build 你的脚本路径.js -o dist --cjs
打包后dist目录下的产物默认是CommonJS规范,天然支持__dirname变量,不需要修改任何业务代码。
方案2:保留ESM输出,改用动态导入puppeteer
如果你必须使用ESM格式输出,把puppeteer的静态导入改为动态导入,保证__dirname赋值完成后再加载puppeteer:
import { dirname } from 'path' import { fileURLToPath } from 'url' // 先完成__dirname全局定义 const __filename = fileURLToPath(import.meta.url) globalThis.__dirname = dirname(__filename) // 动态导入puppeteer,保证执行顺序正确 const puppeteer = await import('puppeteer') // 后续使用puppeteer.default调用原有方法 const browser = await puppeteer.default.launch()
注意动态import返回的是Promise,需要使用await接收,Node.js 14.8以上版本支持顶层await,低版本可以把后续逻辑包在自执行async函数里。
方案3:切换整个项目为CommonJS规范
删掉项目package.json中的"type": "module"配置,把你的脚本后缀改为.cjs,全程用CommonJS规范编写代码,ncc打包后不会出现变量缺失问题。
内容的提问来源于stack exchange,提问作者user1855009
相关产品推荐
相关产品推荐

