メインコンテンツまでスキップ

AWS Lambdaではじめる

このガイドでは、AWS Lambda上でZeltアプリケーションをゼロから構築する手順を説明します。

前提条件

  • Node.js v20以上(またはBun v1.0以上)
  • パッケージマネージャ: pnpm(推奨)、npm、またはbun

AWS Lambdaでは追加で以下が必要です:

インストール

pnpm add @zeltjs/core @zeltjs/adapter-lambda
pnpm add -D @types/aws-lambda esbuild

プロジェクト構成

my-app/
├── src/
│   ├── entry/
│   │   ├── controllers/    # HTTPエンドポイント
│   │   └── commands/       # CLIコマンド
│   ├── services/           # ビジネスロジック
│   ├── configs/            # 設定クラス
│   ├── app.ts              # アプリケーション定義
│   ├── cli.ts              # CLIエントリポイント
│   └── main.ts             # HTTPサーバーエントリポイント
├── package.json
└── tsconfig.json
ディレクトリ用途
entry/外部向けエントリポイント(HTTP、CLI)
services/ビジネスロジック、DIで注入される
configs/環境変数と設定

AWS Lambdaの場合、プロジェクトルートに template.yaml(SAMテンプレート)も追加します。

Hello World

Step 1: Controllerを作成する

src/entry/controllers/hello.controller.ts を作成します:

@Controller('/hello')
export class HelloController {
  @Get('/:name')
  greet(req = request()) {
    const name = req.pathParam('name');
    return { message: `Hello, ${name}!` };
  }
}

Step 2: アプリケーションを作成する

src/app.ts を作成します:

export const app = createApp([http({
    controllers: [HelloController],
  })]);

Step 3: Lambda Handlerを作成する

src/handler.ts を作成します:

const lambdaApp = await onLambda(app);

export const handler = lambdaApp.handler;

onLambda() 関数はアプリをLambdaランタイム用に準備します。返されるのは:

  • handler — API Gateway v2(HTTP API)ハンドラ
  • handlerV1 — API Gateway v1(REST API)ハンドラ
  • shutdown() — アプリケーションをgracefulにシャットダウンします
  • get<T>(Class) — DIコンテナからserviceを解決します

Step 4: SAMテンプレートを設定する

template.yaml を作成します:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Timeout: 30
    Runtime: nodejs20.x

Resources:
  HelloFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: dist/
      Handler: handler.handler
      Events:
        Api:
          Type: HttpApi
          Properties:
            Path: /{proxy+}
            Method: ANY
    Metadata:
      BuildMethod: esbuild
      BuildProperties:
        Minify: true
        Target: es2022
        EntryPoints:
          - src/handler.ts

Outputs:
  ApiEndpoint:
    Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com"

Step 5: デプロイする

sam build
sam deploy --guided

API Gatewayのバージョン

このadapterは両方のAPI Gatewayバージョンをサポートします:

export const handler = lambdaApp.handler;

REST API (v1)

export const handler = lambdaApp.handlerV1;

Warmupオプション

デフォルトでは、onLambda() はコールドスタート時間を最小化するために遅延初期化(warmup: false)を使用します。controllerは最初のリクエストで解決されます。

即時初期化にするには:

const lambdaApp = await onLambda(app, { warmup: true });
オプション挙動用途
warmup: false(デフォルト)controllerは最初のリクエストで解決されるコールドスタートの最適化
warmup: true全controllerが初期化時に解決されるプロビジョンド同時実行

バイナリレスポンス

このadapterは、バイナリレスポンス(画像、音声、動画、octet-stream)をbase64エンコードして自動的に処理します。

@Controller('/files')
export class FileController {
  @Get('/image')
  getImage() {
    const imageBuffer = new Uint8Array([/* ... */]);
    return response()
      .header('Content-Type', 'image/png')
      .body(imageBuffer);
  }
}

次のステップ