我正在使用无服务器框架制作 lambda 函数。该函数使用chartjs-node-canvas生成图形,我使用的是macbook,它在本地正常工作。当我直接或通过代码构建部署到 AWS 时,我遇到了错误:
{
"errorType": "Error",
"errorMessage": "Cannot find module 'canvas'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/index.mjs",
"code": "MODULE_NOT_FOUND",
"requireStack": [
"/var/task/index.js",
"/var/runtime/index.mjs"
],
"stack": [
"Error: Cannot find module 'canvas'",
"Require stack:",
"- /var/task/index.js",
"- /var/runtime/index.mjs",
" at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1026:15)",
" at Function.resolve (node:internal/modules/cjs/helpers:114:19)",
" at fu (/var/task/index.js:1:663)",
" at new ln (/var/task/index.js:3:37199)",
" at Am (/var/task/index.js:58:1375)",
" at processTicksAndRejections (node:internal/process/task_queues:96:5)",
" at async Runtime.Dm [as handler] (/var/task/index.js:58:2652)"
]
}
我尝试过使用图层但不能,也许我做错了。 Chartjs-node-canvas 库依赖于 canvas 库,错误发生在哪里。
我的serverless.yml:
service: report-infra-costs
provider:
name: aws
runtime: nodejs16.x
memorySize: 128
stage: ${opt:stage, env:STAGE, 'prd'}
timeout: 500
region: us-east-1
versionFunctions: false
iamRoleStatements:
- Effect: Allow
Action:
- cloudformation:DescribeStacks
- ce:GetCostAndUsage
- ce:DescribeAccount
- ce:GetDimensionValues
- organizations:DescribeAccount
Resource: "*"
functions:
sendInfraCosts:
handler: index.sendReportInfraCosts
events:
- schedule: cron(0 8 ? * MON *)
custom:
esbuild:
bundle: true
minify: true
exclude: ['aws-sdk']
plugins:
- serverless-esbuild
- serverless-offline
我的buildspec.yml:
version: 0.2
phases:
install:
runtime-versions:
nodejs: 16.x
pre_build:
commands:
- npm install -g serverless
- npm install
build:
commands:
- serverless deploy --stage ${STAGE} --verbose
请帮我解决这个问题
出现此问题是因为
node-canvas
依赖于系统二进制文件。如果您在 Windows 或 Mac 上运行代码并将其部署到使用 Ubuntu 的 AWS Lambda,您将遇到兼容性问题。
要解决此问题,您需要为
node-canvas
创建 Lambda 层:
利用
lambda-layer-canvas-nodejs
层。使用 Lambda Layer Canvas Node.js. 中提供的模板部署该层
从 AWS Lambda 控制台复制该层的 ARN。
通过添加图层 ARN 来更新您的
serverless.yml
文件:
service: report-infra-costs
provider:
name: aws
runtime: nodejs16.x
memorySize: 128
stage: ${opt:stage, env:STAGE, 'prd'}
layers:
- arn:aws:lambda:us-east-1:<account-id>:layer:canvas-nodejs:1 # Replace with your layer ARN
timeout: 500
region: us-east-1
versionFunctions: false
iamRoleStatements:
- Effect: Allow
Action:
- cloudformation:DescribeStacks
- ce:GetCostAndUsage
- ce:DescribeAccount
- ce:GetDimensionValues
- organizations:DescribeAccount
Resource: "*"
functions:
sendInfraCosts:
handler: index.sendReportInfraCosts
events:
- schedule: cron(0 8 ? * MON *)
custom:
esbuild:
bundle: true
minify: true
exclude: ['aws-sdk', 'canvas'] # Add canvas here
plugins:
- serverless-esbuild
- serverless-offline