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

使用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编译:

  1. 在src/lambda目录下添加tsconfig.json,配置编译输出目录(如dist)
  2. 执行tsc命令将TS编译为JS
  3. 修改CDK代码中Code.fromAsset的路径为编译后的输出目录:
code: Code.fromAsset('src/lambda/dist'),

这种方式需要手动处理编译和依赖打包,推荐优先使用NodejsFunction。

内容的提问来源于stack exchange,提问作者Przemek Lach

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:20:23