使用TypeScript的CDK GraphqlApi关联Lambda函数时出现未定义或未导出错误
Lambda使用TypeScript时提示"index.handler is undefined or not exported"的解决方法
Lambda的Node.js运行环境只能执行JavaScript文件,你直接上传TypeScript(.ts)文件时,Node无法识别TS语法,自然找不到导出的handler函数。而.js文件能正常运行是因为Node可以直接执行原生JS代码。
推荐解决方案:使用CDK的NodejsFunction构造
NodejsFunction是CDK专门为TypeScript/JavaScript Lambda提供的构造,内置了自动编译、打包和依赖处理能力,是最便捷的解决方式。
步骤1:安装依赖
安装与你的cdk-lib版本匹配的aws-lambda-nodejs包:
npm install @aws-cdk/aws-lambda-nodejs # 或使用yarn yarn add @aws-cdk/aws-lambda-nodejs
步骤2:修改CDK代码
将原来的Function替换为NodejsFunction,调整代码路径配置:
import * as cdk from 'aws-cdk-lib'; import {aws_appsync} from 'aws-cdk-lib'; import {Construct} from 'constructs'; import {AttributeType, BillingMode, Table} from "aws-cdk-lib/aws-dynamodb"; import * as path from "path"; import {FieldLogLevel} from "aws-cdk-lib/aws-appsync"; import {RetentionDays} from "aws-cdk-lib/aws-logs"; // 导入NodejsFunction import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs'; import { Runtime } from 'aws-cdk-lib/aws-lambda'; export class RelmStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // 保留原有的DynamoDB Table和GraphqlApi代码 const relmTable = new Table(this, 'relm', { billingMode: BillingMode.PAY_PER_REQUEST, tableName: 'relm', partitionKey: { name: 'pk', type: AttributeType.STRING }, sortKey: { name: 'sk', type: AttributeType.STRING } }) const api = new aws_appsync.GraphqlApi(this, 'relm-api', { name: 'relm-api', logConfig: { fieldLogLevel: FieldLogLevel.ALL, excludeVerboseContent: true, retention: RetentionDays.TWO_WEEKS }, schema: aws_appsync.SchemaFile.fromAsset(path.join(__dirname, 'schema.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: aws_appsync.AuthorizationType.API_KEY, apiKeyConfig: { name: 'relm-api-key' } } } }) // 替换原Function定义为NodejsFunction const createLambda = new NodejsFunction(this, 'dialog-create', { functionName: 'dialog-create', runtime: Runtime.NODEJS_14_X, handler: 'handler', // 指定TS文件中导出的函数名 entry: path.join(__dirname, '../src/lambda/index.ts'), // TS文件绝对路径,根据项目结构调整 memorySize: 3008, }) // 保留原有的DataSource、Resolver和权限配置 const createDataSource = api.addLambdaDataSource('create-data-source', createLambda) createDataSource.createResolver('create-resolver', { typeName: 'Mutation', fieldName: 'dialogCreate' }); relmTable.grantWriteData(createLambda); } }
步骤3:保持Lambda的TS代码不变
你的src/lambda/index.ts代码无需修改,NodejsFunction会自动将其编译为JavaScript:
exports.handler = async (event: any) => { console.log('event: ', event) };
可选方案:手动编译TypeScript
如果不想使用NodejsFunction,可以手动处理TS编译:
- 在
src/lambda目录下添加tsconfig.json,配置编译输出目录(如dist) - 执行
tsc命令将TS编译为JS - 修改CDK代码中
Code.fromAsset的路径为编译后的输出目录:
code: Code.fromAsset('src/lambda/dist'),
这种方式需要手动处理编译和依赖打包,推荐优先使用NodejsFunction。
内容的提问来源于stack exchange,提问作者Przemek Lach
相关产品推荐
相关产品推荐

