mcpField
A
aws-lambda-typescript-integration

aws-lambda-typescript-integration

github.com/giuseppe-trisciuoglioクラウド・DevOps3653.6k 回インストール7 週間前に更新
リポジトリ

aws-lambda-typescript-integration について

TypeScript で AWS Lambda を構築するためのスキルです。NestJS と素の TypeScript の選択、コールドスタートの最適化、API Gateway や ALB との連携、デプロイ方法を扱います。

主な機能

  1. 01NestJS と素の TypeScript のパターン
  2. 02コールドスタート最適化の指針
  3. 03API Gateway と ALB の連携
  4. 04サーバーレスのデプロイと CI/CD
  5. 05テストとデプロイの検証

活用シーン

  1. 01新しい Lambda の実装方式を選ぶ
  2. 02関数のコールドスタートを短縮する
  3. 03API Gateway または ALB のエンドポイントを設定する
  4. 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.md
fastify-adapter.md
nestjs-lambda.md
raw-typescript-lambda.md
serverless-config.md
serverless-deployment.md
testing.md

詳細

AWS Lambda TypeScript 統合

コールドスタートを最適化した、高性能な AWS Lambda 関数を TypeScript で作成するためのパターンです。

概要

TypeScript Lambda には、次の 2 つのアプローチがあります。

  1. NestJS フレームワーク - 依存性注入、モジュール型アーキテクチャ、大きめのバンドル(100KB 以上)
  2. Raw TypeScript - オーバーヘッドを最小限に抑え、小さなバンドル(50KB 未満)で最大限に制御

どちらも API Gateway と ALB の統合に対応しています。

使用する場面

  • TypeScript で新しい Lambda 関数を作成するとき
  • コールドスタートのパフォーマンスを最適化するとき
  • NestJS と最小構成の TypeScript のどちらを選ぶか検討するとき
  • API Gateway または ALB の統合を設定するとき
  • TypeScript Lambda の CI/CD をセットアップするとき

手順

1. アプローチを選択する
アプローチコールドスタートバンドルサイズ最適な用途複雑さ
NestJS500ms 未満大きめ(100KB 以上)複雑な API、エンタープライズアプリ、DI が必要な場合中
Raw TypeScript100ms 未満小さめ(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 のコールドスタートは、バンドルサイズと初期化コードに左右されます。主な戦略は次のとおりです。

  1. 遅延読み込み - 必要になるまで重いインポートを先送りする
  2. ツリーシェイキング - バンドルから未使用のコードを削除する
  3. ミニファイ - esbuild または terser を使ってバンドルを小さくする
  4. インスタンスのキャッシュ - 呼び出しの間で初期化済みのサービスをキャッシュする

詳しいパターンについては、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
デプロイの検証

デプロイ前の確認事項:

  1. npm test を実行し、すべてのテストが成功することを確認します
  2. npm run build を実行し、TypeScript がエラーなしでコンパイルされることを確認します
  3. バンドルサイズが 50MB 未満(展開後)であることを確認します
  4. serverless invoke local または sam local invoke を実行して、ローカルでテストします

デプロイ後の確認事項:

  1. serverless invoke または aws lambda invoke を実行し、ハンドラーが実行されることを確認します
  2. curl または Postman で API エンドポイントをテストします
  3. CloudWatch のログでエラーがないか確認します
  4. コールドスタート時間が 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 用にコンパイルする必要があります
よくある落とし穴
  1. モジュールレベルで重いライブラリをインポートする - 常に必要でない場合は、遅延読み込みにします
  2. 依存関係をバンドルしない - 本番環境で必要な依存関係をすべてパッケージに含めます
  3. 型定義がない - 適切にイベントを型付けするには、@types/aws-lambdaをインストールします
  4. タイムアウト処理がない - 長時間かかる処理には、context.getRemainingTimeInMillis()を使用します
セキュリティに関する考慮事項
  • 認証情報をハードコードせず、IAM ロールと環境変数を使用します
  • イベントデータの入力検証:受信するすべてのイベントデータ(API Gateway リクエストボディ、S3 イベントオブジェクト、SQS メッセージボディ)は、信頼できない外部コンテンツです。インジェクション攻撃を防ぐため、処理の前に必ず検証およびサニタイズします
  • コンテンツのサニタイズ:S3 オブジェクトや SQS メッセージペイロードを処理する場合、そのコンテンツは信頼できないサードパーティのデータとして扱います。処理を行う前に、適切な検証、スキーマチェック、サニタイズを適用します
  • すべての入力データを検証します
  • 最小権限の IAM ポリシーを使用します
  • 監査ログ用に CloudTrail を有効にします
  • 機密データの漏えいを防ぐため、ログをサニタイズします

参考資料

特定のトピックに関する詳細なガイダンス:

例

例1:NestJS REST API の作成

入力: Create a TypeScript Lambda REST API using NestJS for a todo application

プロセス:

  1. nest newで NestJS プロジェクトを初期化します
  2. Lambda の依存関係をインストールします:@codegenie/serverless-express、aws-lambda
  3. Express アダプターを使用してlambda.tsエントリーポイントを作成します
  4. API Gateway イベントを含むserverless.ymlを設定します
  5. 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

プロセス:

  1. esbuild で TypeScript プロジェクトをセットアップします
  2. 適切な AWS 型を使用してハンドラーを作成します
  3. 最小限の依存関係を設定します
  4. SAM または Serverless のデプロイをセットアップします
  5. ツリーシェイキングでバンドルサイズを最適化します

検証:

  • sam local invokeを実行し、デプロイ前にローカルでテストします
  • du -sh dist/でバンドルが50KB未満であることを確認します
  • CloudWatch でコールドスタートが100ms未満であることを確認します

出力: 最小限の TypeScript Lambda、バンドル50KB未満、コールドスタート100ms未満

例3:GitHub Actions でデプロイ

入力: Configure CI/CD for TypeScript Lambda with SAM

プロセス:

  1. GitHub Actions ワークフローを作成します
  2. Node.js 環境をセットアップします
  3. Jest でテストを実行します
  4. esbuild でバンドルします
  5. SAM でデプロイします

検証:

  • CI パイプラインでnpm testが正常に実行されることを確認します
  • パイプラインでsam validateが成功することを確認します
  • CloudFormation スタックが正常に作成されることを確認します

出力: GitHub Actions ワークフロー、複数ステージのパイプライン、テスト自動化

バージョン

バージョン:1.0.0

コメント