如何让CDK NodejsFunction引用Lambda Layer的node_modules而非本地依赖?
问题:在CDK的NodejsFunction中让Lambda引用Layer的node_modules而非本地依赖
我在使用CDK的NodejsFunction定义Lambda函数时,想导入Lambda Layer里的node_modules模块。流程是先传入已部署Layer的ARN到NodejsFunction,执行cdk synth --no-staging后用sam local invoke测试,但遇到两个问题:
- 本地CDK项目没安装对应模块时,执行
cdk synth会报Could not resolve <module name>错误; - 用
yarn add <module name>安装后,sam local invoke会优先用本地node_modules里的模块,而非Layer中的。
现有代码
lambda-stack.ts
new lambda.NodejsFunction(this, 'ExportQuotationPDF', { runtime: Runtime.NODEJS_14_X, entry: 'lambda/export-quotation-pdf/index.ts', layers: [ LayerVersion.fromLayerVersionArn( this, 'layer:datefns', 'arn:aws:lambda:ap-northeast-1:1234567890:layer:datefns:1' ) ] })
lambda/sample-function/index.ts
// 若未执行`yarn add date-fns`就运行cdk synth,会报错:Could not resolve "date-fns" // 但执行`yarn add date-fns`后,函数似乎引用的是CDK的node_modules而非Layer中的 import { format } from 'date-fns' export const handler = async () => { try { console.log(format(new Date(), "'Today is a' eeee")) } catch (error) { console.log(error) } }
解决方法
核心思路是让CDK的打包工具(esbuild)跳过目标模块的打包,同时满足本地类型检查,还要让SAM本地测试能模拟Layer环境。
- 将模块安装为开发依赖
不要安装成生产依赖,用开发依赖安装既能满足TypeScript类型检查和cdk synth的模块解析需求,又不会把模块打包进Lambda代码包:
yarn add -D date-fns @types/date-fns
- 配置NodejsFunction排除目标模块
在NodejsFunction的配置中添加bundling选项,告诉esbuild不打包指定模块,Lambda运行时会自动从Layer加载:
new lambda.NodejsFunction(this, 'ExportQuotationPDF', { runtime: Runtime.NODEJS_14_X, entry: 'lambda/export-quotation-pdf/index.ts', layers: [ LayerVersion.fromLayerVersionArn( this, 'layer:datefns', 'arn:aws:lambda:ap-northeast-1:1234567890:layer:datefns:1' ) ], bundling: { externalModules: ['date-fns'], // 标记该模块为外部依赖,不打包进代码 }, })
- SAM本地测试时挂载Layer
本地环境没有远程Layer,需要手动下载并挂载,模拟Lambda运行时的Layer路径:
- 用AWS CLI下载Layer内容:
aws lambda get-layer-version-by-arn --arn arn:aws:lambda:ap-northeast-1:1234567890:layer:datefns:1 --query 'Content.Location' --output text | xargs curl -o datefns-layer.zip unzip datefns-layer.zip -d layers/datefns - 执行本地调用时指定Layer目录:
sam local invoke ExportQuotationPDFFunction --layer-path layers/datefns/nodejs
原理说明
- 开发依赖安装:解决TypeScript类型检查和esbuild模块解析的问题,避免
cdk synth报错; externalModules配置:让esbuild知道该模块不需要打包,Lambda运行时会从Layer的/opt/nodejs/node_modules目录加载;- SAM本地挂载:手动模拟Lambda运行时的Layer环境,确保本地测试和线上行为一致。
内容的提问来源于stack exchange,提问作者kusumoto_teruya
相关产品推荐
相关产品推荐

