PAYATHON 2026

Serverless Lambda Layers 报错 Cannot find module 'request'

支付阿杰

结论

serverless deploy 会根据 layers 配置创建 Lambda Layer,但不会自动将其关联到所有函数。

当前配置还通过 package.exclude 排除了 node_modules/**,因此函数部署包中不包含 request。如果函数配置也没有显式引用 nodejs Layer,运行时就会报错:

Cannot find module 'request'

要正常加载依赖,需要满足以下两个条件:

  1. Layer 压缩包的目录结构符合 Node.js Lambda Layer 规范。
  2. 每个使用该依赖的 Lambda 函数都显式关联这个 Layer。

正确的 Layer 目录结构

对于 Node.js,依赖必须放在 Layer 压缩包的 nodejs/node_modules 目录中:

nodejs.zip
└── nodejs/
    ├── package.json
    └── node_modules/
        └── request/

可以使用以下命令生成压缩包:

mkdir -p nodejs
cd nodejs
npm init -y
npm install request
cd ..
zip -r nodejs.zip nodejs

不要只压缩 node_modules 目录里的内容。Lambda 挂载 Layer 后,会从类似以下路径的位置查找 Node.js 模块:

/opt/nodejs/node_modules

在 Serverless 中关联 Layer

顶层的 Layer 定义可以继续保留:

layers:
  nodejs:
    package:
      artifact: nodejs.zip
    compatibleRuntimes:
      - nodejs8.10
    allowedAccounts:
      - "*"

还需要在函数配置中显式添加 layers。如果函数直接定义在主配置文件中,可以这样写:

functions:
  payment:
    handler: src/handlers/payment.handler
    layers:
      - Ref: NodejsLambdaLayer

NodejsLambdaLayer 是 Serverless 根据 Layer 名称 nodejs 生成的 CloudFormation 逻辑 ID。

如果函数配置来自外部文件:

functions:
  - '${file(src/handlers/${opt:api, "payment"}.serverless.yml)}'

则需要在对应的外部文件中为函数添加 Layer 引用,例如:

payment:
  handler: payment.handler
  layers:
    - Ref: NodejsLambdaLayer

具体层级要与外部文件当前导出的函数结构保持一致。

为什么手动上传相同的 ZIP 可以运行

“相同 ZIP”不代表最终的 Lambda 配置也相同。可能出现以下情况:

  • 手动操作时,ZIP 被当作函数代码包上传,其中直接包含了可加载的依赖。
  • 手动创建 Layer 后,又在 AWS Console 中将其关联到了函数。
  • Console 中的函数保留了之前关联的 Layer,而 Serverless 部署创建的是另一个没有关联到函数的新 Layer 版本。
  • Serverless 部署的函数包排除了 node_modules,但手动上传的实际函数包仍包含依赖。

因此,需要比较函数的最终配置,不能只比较 ZIP 文件。可以打开 AWS Console 的函数页面,检查 Layers 区域,确认 Serverless 创建的 Layer 版本是否已经关联到该函数。

建议的完整配置方式

provider:
  name: aws
  runtime: nodejs8.10
  stage: ${opt:api-type, 'uat'}-${opt:api, 'payment'}
  region: ca-central-1
  timeout: 30
  memorySize: 128

package:
  exclude:
    - node_modules/**
    - nodejs/**

layers:
  nodejs:
    package:
      artifact: nodejs.zip
    compatibleRuntimes:
      - nodejs8.10
    allowedAccounts:
      - "*"

functions:
  payment:
    handler: src/handlers/payment.handler
    layers:
      - Ref: NodejsLambdaLayer

部署后,可以检查生成的 CloudFormation 模板,确认函数资源的 Layers 属性中包含 Layer 引用:

serverless package

然后查看:

.serverless/cloudformation-template-update-stack.json

其中应出现类似以下配置:

{
  "Layers": [
    {
      "Ref": "NodejsLambdaLayer"
    }
  ]
}

注意事项

request 已停止维护。现有项目仍可以通过 Layer 加载它,新代码则更适合使用运行时支持的 HTTP 能力或仍在维护的客户端库。

nodejs8.10 也已停止受 AWS Lambda 支持,应尽快升级到当前受支持的 Node.js 运行时。升级后需要重新安装依赖并构建 Layer。如果依赖包含原生二进制模块,还必须在与 Lambda 运行环境兼容的 Linux 环境中构建。

备注:内容仅供参考。