如何在CDK中打包TypeScript编写的AppSync解析器?
在CDK中打包AppSync TypeScript解析器的可行方案
AppSync支持用TypeScript编写解析器,但CDK的AppsyncFunction构造仅接受编译后的JS文件,且没有像NodejsLambda那样内置的esbuild打包能力,以下是几种解决思路:
方案一:预编译TS文件(简单直接)
提前把TS解析器编译成JS,再传入CDK:
- 给解析器目录单独配置
tsconfig.json,指定target: "ES2020"(匹配AppSync JS 1.0 runtime)、输出目录等规则。 - 在
package.json里添加编译脚本:"build:resolvers": "tsc --project ./resolvers/tsconfig.json",部署前执行该命令生成JS文件。 - 在CDK中直接引用编译后的JS路径:
const resolverFunc = new appsync.AppsyncFunction(this, "MyResolverFunc", { name: "my_resolver", api, dataSource: dynamoDataSource, code: appsync.Code.fromAsset( path.join(__dirname, "../path/to/compiled/my_resolver.js") // ✅ 指向编译完成的JS文件 ), runtime: appsync.FunctionRuntime.JS_1_0_0, });
方案二:CDK集成esbuild动态编译
在CDK synth阶段用esbuild自动把TS转成JS,无需手动预编译:
- 安装esbuild依赖:
npm install esbuild --save-dev - 编写打包工具函数:
import * as esbuild from 'esbuild'; import * as path from 'path'; import * as fs from 'fs-extra'; import { Construct } from 'constructs'; function buildResolverTs(scope: Construct, tsFilePath: string): appsync.Code { const outputDir = path.join(__dirname, '.tmp', 'resolvers'); const outputJsPath = path.join(outputDir, path.basename(tsFilePath).replace('.ts', '.js')); // 创建临时输出目录 fs.ensureDirSync(outputDir); // esbuild编译TS到JS esbuild.buildSync({ entryPoints: [tsFilePath], bundle: true, // 有外部依赖时开启 platform: 'node', target: 'es2020', outfile: outputJsPath, minify: true, // 可选,压缩代码体积 }); return appsync.Code.fromAsset(outputDir, { fileName: path.basename(outputJsPath), }); } - 在CDK中直接传入TS文件路径:
const resolverFunc = new appsync.AppsyncFunction(this, "MyResolverFunc", { name: "my_resolver", api, dataSource: dynamoDataSource, code: buildResolverTs(this, path.join(__dirname, "../path/to/my_resolver.ts")), // ✅ 直接传TS文件 runtime: appsync.FunctionRuntime.JS_1_0_0, });
方案三:封装自定义构造复用逻辑
如果有大量TS解析器,可以封装一个类似NodejsLambda的自定义构造,内置打包逻辑:
import * as appsync from 'aws-cdk-lib/aws-appsync'; import * as path from 'path'; import { Construct } from 'constructs'; interface NodejsAppsyncFunctionProps extends Omit<appsync.AppsyncFunctionProps, 'code'> { entry: string; // TS解析器文件路径 } class NodejsAppsyncFunction extends appsync.AppsyncFunction { constructor(scope: Construct, id: string, props: NodejsAppsyncFunctionProps) { const { entry, ...restProps } = props; const outputDir = path.join(__dirname, '.tmp', 'appsync-functions', id); const outputJsPath = path.join(outputDir, path.basename(entry).replace('.ts', '.js')); // 自动执行esbuild打包 require('esbuild').buildSync({ entryPoints: [entry], bundle: true, platform: 'node', target: 'es2020', outfile: outputJsPath, }); super(scope, id, { ...restProps, code: appsync.Code.fromAsset(outputDir, { fileName: path.basename(outputJsPath) }), runtime: appsync.FunctionRuntime.JS_1_0_0, }); } }
使用时直接传入TS路径即可:
const resolverFunc = new NodejsAppsyncFunction(this, "MyResolverFunc", { name: "my_resolver", api, dataSource: dynamoDataSource, entry: path.join(__dirname, "../path/to/my_resolver.ts"), });
内容的提问来源于stack exchange,提问作者fedonev
相关产品推荐
相关产品推荐

