You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AWS CDK TypeScript创建的Lambda Layer无法被Lambda函数导入的问题

问题:Lambda Layer模块无法导入的排查与修复

问题场景

使用API Gateway、Lambda与AWS CDK(TypeScript)构建无服务器API时,创建Lambda Layer并在Lambda函数中复用,调用函数时出现Cannot find module '/opt/nodejs/calculator'错误。

相关代码

Lambda Handler代码(路径:{root}/api/src/handlers/layer-lambda.handlers.ts)

import { add } from "/opt/nodejs/calculator";
import {APIGatewayProxyHandler} from "aws-lambda";

export const calculate: APIGatewayProxyHandler = async (event) => {
    const result = add(1, 2);

    return {
        statusCode: 200,
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
            message: `1 + 2 = ${result}`
        })
    }
}

Lambda Layer代码(路径:{root}/api/src/layers/calculator/nodejs/calculator.js)

export const add = (num1: number, num2: number) => {
    return num1 + num2;
}

Layer的package.json(路径:{root}/api/src/layers/calculator/nodejs/package.json)

{
  "name": "calculator",
  "version": "0.1.0",
  "dependencies": {}
}

tsconfig.json路径配置

{
   "compilerOptions": {
      // 其他配置
      "paths": {
      "/opt/nodejs/calculator": [
        "src/layers/calculator/nodejs/calculator"
      ]
    }
   }
}

CDK中的Layer与Lambda配置

const layerVersion = new LayerVersion(this, getStageSpecificResourceId(`calculator-layer`), {
            compatibleRuntimes: [ Runtime.NODEJS_18_X ],
            compatibleArchitectures: [ Architecture.X86_64 ],
            code: Code.fromAsset(path.resolve(__dirname, `../../api/src/layers/calculator`)),
            description: `Simple calculator lambda layer`,
        });

const calHandler = new NodejsFunction(this, `calculate`, {
    entry: path.resolve(__dirname, `../../api/src/handlers/layer-lambda.handlers.ts`),
    functionName: getVariantSpecificResourceId(`calculate`),
    handler: `calculate`,
    memorySize: 1024,
    runtime: Runtime.NODEJS_18_X,
    timeout: cdk.Duration.seconds(30),
    bundling: {
        sourceMap: true,
        minify: false,
        externalModules: [ `/opt/nodejs/calculator` ],
    },
    environment: {},
    layers: [
        layerVersion,
    ],
});

this.api.root.addResource("calculate").addMethod("GET", new LambdaIntegration(calHandler));

错误信息

{
    "errorType": "Runtime.ImportModuleError",
    "errorMessage": "Error: Cannot find module '/opt/nodejs/calculator'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/index.mjs",
    "stack": [
        "Runtime.ImportModuleError: Error: Cannot find module '/opt/nodejs/calculator'",
        "Require stack:",
        "- /var/task/index.js",
        "- /var/runtime/index.mjs",
        "    at _loadUserApp (file:///var/runtime/index.mjs:1087:17)",
        "    at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1119:21)",
        "    at async start (file:///var/runtime/index.mjs:1282:23)",
        "    at async file:///var/runtime/index.mjs:1288:1"
    ]
}

错误原因分析

  1. Layer代码未编译为JavaScript:Layer中的calculator.js实际是TypeScript代码,但扩展名错误标注为.js,Lambda Node.js运行时无法直接执行TS代码,必须编译为JS。
  2. externalModules配置错误:bundling.externalModules中配置绝对路径/opt/nodejs/calculator无效,该配置需要指定模块名称(对应Layer中package.json的name字段),而非运行时绝对路径。
  3. Layer目录结构与打包逻辑问题:CDK打包Layer时,未将TS代码编译为JS,导致部署到Lambda的Layer中没有可执行的JS文件;同时Node.js模块查找逻辑是从/opt/nodejs/node_modules下查找模块,直接用绝对路径导入不符合模块解析规则。

修复步骤

1. 修正Layer代码的扩展名与编译

  • 将{root}/api/src/layers/calculator/nodejs/calculator.js重命名为calculator.ts。
  • 在Layer的nodejs目录下添加tsconfig.json(或复用项目根目录的配置),确保编译输出到当前目录:
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "outDir": ".",
    "strict": true,
    "moduleResolution": "node"
  }
}

2. 调整CDK中Layer的打包逻辑

让CDK在打包Layer时自动编译TS代码,修改LayerVersion的code配置:

const layerVersion = new LayerVersion(this, getStageSpecificResourceId(`calculator-layer`), {
  compatibleRuntimes: [Runtime.NODEJS_18_X],
  compatibleArchitectures: [Architecture.X86_64],
  code: Code.fromAsset(path.resolve(__dirname, `../../api/src/layers/calculator`), {
    bundling: {
      image: Runtime.NODEJS_18_X.bundlingImage,
      command: [
        'bash', '-c',
        'cd nodejs && npm install && npx tsc && rm -rf node_modules && cd .. && cp -r nodejs/* /asset-output/'
      ],
    },
  }),
  description: `Simple calculator lambda layer`,
});

这段命令会进入nodejs目录,安装依赖(如果有),编译TS代码,清理不必要的依赖,最后将编译后的内容复制到Layer的输出目录。

3. 修正Lambda函数的导入与配置

  • 修改Lambda Handler的导入语句,使用模块名(对应Layer中package.json的name字段):
import { add } from "calculator";
  • 更新tsconfig.json的paths配置,对应模块名:
{
  "compilerOptions": {
    // 其他配置
    "paths": {
      "calculator": [
        "src/layers/calculator/nodejs/calculator"
      ]
    }
  }
}
  • 调整NodejsFunction的externalModules配置,使用模块名:
bundling: {
  sourceMap: true,
  minify: false,
  externalModules: ["calculator"],
},

4. 验证Layer目录结构

部署后,Lambda运行时会将Layer挂载到/opt,正确的目录结构应为:

/opt
└── nodejs
    ├── package.json
    └── calculator.js

Node.js会自动将/opt/nodejs加入模块查找路径,因此可以直接通过模块名calculator导入。

验证

重新部署CDK栈后,调用API Gateway的/calculate接口,应返回{"message":"1 + 2 = 3"},无模块导入错误。

内容的提问来源于stack exchange,提问作者Wai Yan Hein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 08:10:00