使用SAM本地调用CDK编译JS代码时遇__dirname未定义错误
问题根源
错误来自aws-cdk-lib/core/lib/custom-resource-provider/custom-resource-provider.js,因为Node.js ES模块(ESM)环境中不存在CommonJS的__dirname变量,而CDK生成的代码或依赖模块在ESM环境下尝试访问了它——你的代码没调用,但依赖的CDK内部代码用到了。
解决方法
调整Lambda函数的打包格式
如果用CDK定义Lambda,在Function配置里明确指定打包为CommonJS:new lambda.Function(this, 'MyFunction', { // 其他配置 bundling: { format: cdk.BundlingFormat.CJS, // 强制生成CommonJS格式 // 其他打包配置 }, });同时检查项目根目录的
package.json,如果有"type": "module"字段,要么删除它(让Node默认使用CommonJS),要么给该函数的单独目录加一个package.json,里面写"type": "commonjs"来覆盖全局配置。临时模拟__dirname(ESM环境下)
如果你必须用ESM模式,在函数代码最顶部添加以下代码,手动定义__dirname并挂载到全局:import { fileURLToPath } from 'url'; import { dirname } from 'path'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); global.__dirname = __dirname;这只是临时 workaround,优先推荐调整打包格式的方案。
检查SAM运行环境配置
确认执行sam local invoke时没有设置强制启用ESM的环境变量,比如NODE_OPTIONS=--experimental-modules,如果有就移除该环境变量后再测试。
为什么其他函数正常?
其他函数可能没有依赖aws-cdk-lib的自定义资源提供者模块,或者它们的打包格式是CommonJS,Node.js在CommonJS环境下会自动提供__dirname,所以不会触发这个错误。
内容的提问来源于stack exchange,提问作者stuart

