aws-lambda-typescript-integration
aws-lambda-typescript-integration について
TypeScript で AWS Lambda を構築するためのスキルです。NestJS と素の TypeScript の選択、コールドスタートの最適化、API Gateway や ALB との連携、デプロイ方法を扱います。
主な機能
- 01NestJS と素の TypeScript のパターン
- 02コールドスタート最適化の指針
- 03API Gateway と ALB の連携
- 04サーバーレスのデプロイと CI/CD
- 05テストとデプロイの検証
活用シーン
- 01新しい Lambda の実装方式を選ぶ
- 02関数のコールドスタートを短縮する
- 03API Gateway または ALB のエンドポイントを設定する
- 04Lambda のデプロイパイプラインを構築する
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ giuseppe-trisciuoglio/ developer-kit --skill aws-lambda-typescript-integrationインストール後、Claude Code で/aws-lambda-typescript-integrationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/express-adapter.mdfastify-adapter.mdnestjs-lambda.mdraw-typescript-lambda.mdserverless-config.mdserverless-deployment.mdtesting.md詳細
AWS Lambda TypeScript 統合
コールドスタートを最適化した、高性能な AWS Lambda 関数を TypeScript で作成するためのパターンです。
概要
TypeScript Lambda には、次の 2 つのアプローチがあります。
- NestJS フレームワーク - 依存性注入、モジュール型アーキテクチャ、大きめのバンドル(100KB 以上)
- Raw TypeScript - オーバーヘッドを最小限に抑え、小さなバンドル(50KB 未満)で最大限に制御
どちらも API Gateway と ALB の統合に対応しています。
使用する場面
- TypeScript で新しい Lambda 関数を作成するとき
- コールドスタートのパフォーマンスを最適化するとき
- NestJS と最小構成の TypeScript のどちらを選ぶか検討するとき
- API Gateway または ALB の統合を設定するとき
- TypeScript Lambda の CI/CD をセットアップするとき
手順
1. アプローチを選択する
| アプローチ | コールドスタート | バンドルサイズ | 最適な用途 | 複雑さ |
|---|---|---|---|---|
| NestJS | 500ms 未満 | 大きめ(100KB 以上) | 複雑な API、エンタープライズアプリ、DI が必要な場合 | 中 |
| Raw TypeScript | 100ms 未満 | 小さめ(50KB 未満) | シンプルなハンドラー、マイクロサービス、依存関係を最小限にしたい場合 | 低 |
2. プロジェクト構成
NestJS の構成
my-nestjs-lambda/
├── src/
│ ├── app.module.ts
│ ├── main.ts
│ ├── lambda.ts # Lambda entry point
│ └── modules/
│ └── api/
├── package.json
├── tsconfig.json
└── serverless.yml
Raw TypeScript の構成
my-ts-lambda/
├── src/
│ ├── handlers/
│ │ └── api.handler.ts
│ ├── services/
│ └── utils/
├── dist/ # Compiled output
├── package.json
├── tsconfig.json
└── template.yaml
3. 実装例
詳しい実装ガイドについては、リファレンスのセクションをご覧ください。簡単な例を以下に示します。
NestJS ハンドラー:
// lambda.ts
import { NestFactory } from '@nestjs/core';
import { ExpressAdapter } from '@nestjs/platform-express';
import serverlessExpress from '@codegenie/serverless-express';
import { Context, Handler } from 'aws-lambda';
import express from 'express';
import { AppModule } from './src/app.module';
let cachedServer: Handler;
async function bootstrap(): Promise<Handler> {
const expressApp = express();
const adapter = new ExpressAdapter(expressApp);
const nestApp = await NestFactory.create(AppModule, adapter);
await nestApp.init();
return serverlessExpress({ app: expressApp });
}
export const handler: Handler = async (event: any, context: Context) => {
if (!cachedServer) {
cachedServer = await bootstrap();
}
return cachedServer(event, context);
};
Raw TypeScript ハンドラー:
// src/handlers/api.handler.ts
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
export const handler = async (
event: APIGatewayProxyEvent,
context: Context
): Promise<APIGatewayProxyResult> => {
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: 'Hello from TypeScript Lambda!' })
};
};
主な概念
コールドスタートの最適化
TypeScript のコールドスタートは、バンドルサイズと初期化コードに左右されます。主な戦略は次のとおりです。
- 遅延読み込み - 必要になるまで重いインポートを先送りする
- ツリーシェイキング - バンドルから未使用のコードを削除する
- ミニファイ - esbuild または terser を使ってバンドルを小さくする
- インスタンスのキャッシュ - 呼び出しの間で初期化済みのサービスをキャッシュする
詳しいパターンについては、Raw TypeScript Lambdaをご覧ください。
接続管理
モジュールレベルでクライアントを作成し、再利用します。
// GOOD: Initialize once, reuse across invocations
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
const dynamoClient = new DynamoDBClient({ region: process.env.AWS_REGION });
export const handler = async (event: APIGatewayProxyEvent) => {
// Use dynamoClient - already initialized
};
環境設定
// src/config/env.config.ts
export const env = {
region: process.env.AWS_REGION || 'us-east-1',
tableName: process.env.TABLE_NAME || '',
debug: process.env.DEBUG === 'true',
};
// Validate required variables
if (!env.tableName) {
throw new Error('TABLE_NAME environment variable is required');
}
ベストプラクティス
メモリとタイムアウトの設定
- メモリ:NestJS では 512MB、Raw TypeScript では 256MB から始めます
- タイムアウト:コールドスタートと予想される処理時間に基づいて設定します
- NestJS:コールドスタートのバッファーとして 10~30 秒
- Raw TypeScript:通常は 3~10 秒で十分です
依存関係
package.json は最小限に保ちます。
{
"dependencies": {
"aws-lambda": "^3.1.0",
"@aws-sdk/client-dynamodb": "^3.450.0"
},
"devDependencies": {
"typescript": "^5.3.0",
"esbuild": "^0.19.0"
}
}
エラー処理
構造化されたエラーと適切な HTTP ステータスコードを返します。
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
try {
const result = await processEvent(event);
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(result)
};
} catch (error) {
console.error('Error processing request:', error);
return {
statusCode: 500,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ error: 'Internal server error' })
};
}
};
ロギング
CloudWatch Insights 用に構造化ログを使用します。
const log = (level: string, message: string, meta?: object) => {
console.log(JSON.stringify({
level,
message,
timestamp: new Date().toISOString(),
...meta
}));
};
log('info', 'Request processed', { requestId: context.awsRequestId });
デプロイの選択肢
クイックスタート
Serverless Framework:
service: my-typescript-api
provider:
name: aws
runtime: nodejs20.x
functions:
api:
handler: dist/handler.handler
events:
- http:
path: /{proxy+}
method: ANY
AWS SAM:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: dist/
Handler: handler.handler
Runtime: nodejs20.x
Events:
ApiEvent:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
デプロイの検証
デプロイ前の確認事項:
npm testを実行し、すべてのテストが成功することを確認しますnpm run buildを実行し、TypeScript がエラーなしでコンパイルされることを確認します- バンドルサイズが 50MB 未満(展開後)であることを確認します
serverless invoke localまたはsam local invokeを実行して、ローカルでテストします
デプロイ後の確認事項:
serverless invokeまたはaws lambda invokeを実行し、ハンドラーが実行されることを確認します- curl または Postman で API エンドポイントをテストします
- CloudWatch のログでエラーがないか確認します
- コールドスタート時間が SLA を満たしていることを確認します
CI/CD を含む完全なデプロイ設定については、Serverless Deploymentをご覧ください。
制約と警告
Lambda の制限
- デプロイパッケージ:展開後の最大サイズは 250MB(圧縮後は 50MB)
- メモリ:128MB~10GB
- タイムアウト:最大 15 分
- 同時実行数:デフォルトは 1000(変更可能)
- 環境変数:合計サイズは 4KB
TypeScript 固有の考慮事項
- バンドルサイズ:TypeScript は JavaScript にコンパイルされます。サイズを最小限にするにはバンドラーを使用します
- コールドスタート:Node.js 20.x が最良のパフォーマンスを発揮します
- 依存関係:共有依存関係には Lambda Layers を使用します
- ネイティブモジュール:Amazon Linux 2 用にコンパイルする必要があります
よくある落とし穴
- モジュールレベルで重いライブラリをインポートする - 常に必要でない場合は、遅延読み込みにします
- 依存関係をバンドルしない - 本番環境で必要な依存関係をすべてパッケージに含めます
- 型定義がない - 適切にイベントを型付けするには、
@types/aws-lambdaをインストールします - タイムアウト処理がない - 長時間かかる処理には、
context.getRemainingTimeInMillis()を使用します
セキュリティに関する考慮事項
- 認証情報をハードコードせず、IAM ロールと環境変数を使用します
- イベントデータの入力検証:受信するすべてのイベントデータ(API Gateway リクエストボディ、S3 イベントオブジェクト、SQS メッセージボディ)は、信頼できない外部コンテンツです。インジェクション攻撃を防ぐため、処理の前に必ず検証およびサニタイズします
- コンテンツのサニタイズ:S3 オブジェクトや SQS メッセージペイロードを処理する場合、そのコンテンツは信頼できないサードパーティのデータとして扱います。処理を行う前に、適切な検証、スキーマチェック、サニタイズを適用します
- すべての入力データを検証します
- 最小権限の IAM ポリシーを使用します
- 監査ログ用に CloudTrail を有効にします
- 機密データの漏えいを防ぐため、ログをサニタイズします
参考資料
特定のトピックに関する詳細なガイダンス:
- NestJS Lambda - NestJS の完全なセットアップ、依存性注入、Express/Fastify アダプター
- Raw TypeScript Lambda - 最小限のハンドラーパターン、バンドル、ツリーシェイキング
- Serverless Config - Serverless Framework と SAM の設定
- Serverless Deployment - CI/CD パイプライン、環境管理
- Testing - Jest、統合テスト、SAM Local
例
例1:NestJS REST API の作成
入力: Create a TypeScript Lambda REST API using NestJS for a todo application
プロセス:
nest newで NestJS プロジェクトを初期化します- Lambda の依存関係をインストールします:
@codegenie/serverless-express、aws-lambda - Express アダプターを使用して
lambda.tsエントリーポイントを作成します - API Gateway イベントを含む
serverless.ymlを設定します - Serverless Framework でデプロイします
検証:
serverless invoke local -f apiを実行し、ハンドラーが動作することを確認します- バンドルサイズが250MB未満であることを確認します
- デプロイしたエンドポイントが200 OKを返すことをテストします
出力: REST API、DynamoDB 統合、デプロイ設定を備えた NestJS プロジェクト
例2:TypeScript Lambda の作成
入力: Create a minimal TypeScript Lambda function with optimal cold start
プロセス:
- esbuild で TypeScript プロジェクトをセットアップします
- 適切な AWS 型を使用してハンドラーを作成します
- 最小限の依存関係を設定します
- SAM または Serverless のデプロイをセットアップします
- ツリーシェイキングでバンドルサイズを最適化します
検証:
sam local invokeを実行し、デプロイ前にローカルでテストしますdu -sh dist/でバンドルが50KB未満であることを確認します- CloudWatch でコールドスタートが100ms未満であることを確認します
出力: 最小限の TypeScript Lambda、バンドル50KB未満、コールドスタート100ms未満
例3:GitHub Actions でデプロイ
入力: Configure CI/CD for TypeScript Lambda with SAM
プロセス:
- GitHub Actions ワークフローを作成します
- Node.js 環境をセットアップします
- Jest でテストを実行します
- esbuild でバンドルします
- SAM でデプロイします
検証:
- CI パイプラインで
npm testが正常に実行されることを確認します - パイプラインで
sam validateが成功することを確認します - CloudFormation スタックが正常に作成されることを確認します
出力: GitHub Actions ワークフロー、複数ステージのパイプライン、テスト自動化
バージョン
バージョン:1.0.0