4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【続】GitHub ActionsでAWS Lambdaを簡単かつ爆速でデプロイしよう!【TypeScript編】

Last updated at Posted at 2025-09-09

はじめに

2025年8月にAWS Lambdaのアップデートがあり,デプロイ用のアクションがaws-actionsより提供されるようになりました!
先日投稿した記事では,このアクションを使用し,従来の方法よりも簡単にかつ高速にLambda関数をPythonのランタイムでデプロイすることができるようになったので,その方法をまとめました.

この記事では,その続編として,コードをTypeScriptで記述したLambda関数をローカルからデプロイします.

従来のAWS Lambda with TypeScript

Lambda関数をTypeScriptで記述することの需要は当然あります.静的型付け言語による開発は間違いなく魅力的です.
自分も所属しているKDDIアジャイル開発センターの記事でもTypeScriptでLambda関数を記述する方法についてまとめたものがあります.

しかし,従来のTypeScriptを用いたLambda関数での開発はそれなりにめんどくさいです(慣れれば簡単みたいですが).
TypeScriptは実行前にJavaScriptへのトランスパイルが必要であり,依存ライブラリも一緒にパッケージング(バンドル)する必要があるため,デプロイまでの手順が複雑になりがちでした.

これらの複雑な手順をIaCで定義するのはそれなりにめんどくさいです.そのため,IaCを使用せずにデプロイできるようになった今回のアップデートで,TypeScriptsを用いてのLambda関数での開発がかなり簡単になりました.しかもnode_module.gitingoreに含めることができるのでデプロイもとても高速です.
この記事ではその方法について簡単にまとめます.

実装

今回はhello from TypeScript!というメッセージが入ったjsonが返ってくるシンプルなLambda関数をデプロイします.

ディレクトリ構成

TypeScriptのプロジェクトでは,ソースコードを管理するsrcディレクトリと,トランスパイル後のJavaScriptが出力されるdistディレクトリを分けるのが一般的です.

├── .github
│   └── workflows
│       └── deploy_lambda.yml
└── hello_lambda_ts
    ├── package.json
    ├── tsconfig.json
    └── src
        └── index.ts

src/index.tsがLambda関数の本体です.hello_lambda_tsディレクトリが1つのLambda関数プロジェクトになります.

IAMユーザーを用意する

この手順は前回のPython編と全く同じです.Lambda関数をデプロイするためのアクセスキーとシークレットアクセスキー,そしてLambda関数に割り当てるIAMロールのARNを用意し,GitHubリポジトリのSecretsに登録してください.

詳細は前回の記事を参照してください.

TypeScriptプロジェクトをセットアップする

まず,hello_lambda_tsディレクトリを作成し,その中でNode.jsプロジェクトを初期化します.

mkdir hello_lambda_ts
cd hello_lambda_ts
npm init -y

次に関数の開発に必要なライブラリをインストールします.

typescript: TypeScriptコンパイラ

esbuild: 高速なTypeScriptのトランスパイラ兼バンドラ

@types/node, @types/aws-lambda: 型定義ファイル

npm install --save-dev typescript esbuild @types/node @types/aws-lambda

これらの作業で発生した以下のディレクトリ,ファイルは.gitignoreに追加してください.

.gitignore
# Node.js
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# TypeScript
*.tsbuildinfo
dist/
build/

今回は,トランスパイルとバンドルを高速に行えるesbuildを使用します.

デプロイする関数と設定ファイルを用意する
hello_lambda_tsディレクトリ内に以下のファイルを作成します.

tsconfig.json

TypeScriptのコンパイル設定を記述します.

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist"
  },
  "include": ["src/**/*"]
}

package.json

esbuildを使ってビルドするためのスクリプトをscriptsに追加します.
"main"のエントリポイントもビルド後のファイルを指すように変更しておきましょう.

{
  "name": "hello_lambda_ts",
  "version": "1.0.0",
  "description": "",
  "main": "dist/index.js",
  "scripts": {
    "build": "esbuild src/index.ts --bundle --minify --sourcemap --platform=node --target=node20 --outfile=dist/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "devDependencies": {
    "@types/aws-lambda": "^8.10.138",
    "@types/node": "^20.12.12",
    "esbuild": "^0.25.9",
    "typescript": "^5.4.5"
  }
}

今回はnodeのバージョンを20.xとしているため,npm installした時のバージョンが24などになっている場合は上記ののjsonと同じように20.xでするか,後述するymlファイルのNODE_VERSION24.xなどにしてpackage.jsonpackage-lock.json, deploy_lambda.ymlでバージョンの齟齬が起こらないようにしてください.
AIで解決できる簡単なエラーが発生するだけなので,とりあえずデプロイしてエラーが発生したらAIに噛ませるでもいいと思いますが
それ以外はnpm installした時のままで大丈夫です.

buildスクリプトは,src/index.tsをエントリーポイントとして,依存関係をすべてバンドルし,Node.js 20.x環境で実行可能な単一のdist/index.jsファイルを生成します.

src/index.ts

message: hello from TypeScript!を返すだけのシンプルなhandlerです.

import { APIGatewayProxyHandler } from 'aws-lambda';

export const handler: APIGatewayProxyHandler = async (event, context) => {
  return {
    statusCode: 200,
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      message: 'hello from TypeScript!',
    }),
  };
};

ymlファイルを用意する

以下のymlがGitHub Actionsで動作するworkflowです.Python編との違いは,Node.jsのセットアップ,依存関係のインストール,ビルドステップです.

name: Deploy-Lambda-TypeScript

on:
  push:
    branches:
      - "main"
  pull_request:
    paths:
      - "hello_lambda_ts/**"
      - ".github/workflows/deploy_lambda.yml"

permissions:
  id-token: write
  contents: read

defaults:
  run:
    working-directory: "hello_lambda_ts"

env:
  NODE_VERSION: 20.x
  function-name: hello_lambda_ts_actions
  lambda-role-arn: ${{ secrets.LAMBDA_ROLE_ARN }}

jobs:
  main:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "${{ env.NODE_VERSION }}"
      
      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      - name: Deploy Lambda
        uses: aws-actions/aws-lambda-deploy@v1.0.1
        with:
          function-name: ${{ env.function-name }}
          code-artifacts-dir: ./hello_lambda_ts/dist
          handler: index.handler
          runtime: nodejs${{ env.NODE_VERSION }}
          role: ${{ env.lambda-role-arn }}
          timeout: 30

Deploy Lambdaステップの解説 (TypeScript編)

Python編とほぼ同じですが,いくつかTypeScript特有の注意点があります.

code-artifacts-dir

esbuildによって生成されたJavaScriptファイルが格納されているdistディレクトリを指定します.GitHub Actionsのルートからのパスで指定するため,./hello_lambda_ts/distとしています.

handler

ファイル名.エクスポートした関数名の形式で指定します.今回はdist/index.jsファイルの中のhandler関数なので,index.handlerとなります.

runtime

nodejs20.xのように,使用したいNode.jsのバージョンを指定します.

実装完了

これで準備は完了です.mainブランチへのpushかプルリクエスト作成時,更新時にLambda関数のビルドとデプロイが実行されます.デプロイが完了すると,マネジメントコンソールで以下のように確認でき,[Test]タブから実行テストも行えます.
スクリーンショット 2025-09-08 13.45.39.png

めちゃくちゃ簡単にTypeScriptでLambda関数を作成し,デプロイすることができました.

付録

TypeScriptでの開発をより実用的にするための付録です.

付録1:ローカルでも実行したい

ts-nodeを使うと,TypeScriptファイルを直接実行できるのでローカルでの動作確認が簡単です.

npm install --save-dev ts-node

テスト用のコードをsrc/index.tsの末尾に追記します.

// ... handler関数のコード ...

// スクリプトが直接実行された場合にテストコードを呼び出す
if (require.main === module) {
  console.log("--- Running Local Test ---");
  // @ts-ignore
  handler({}, {}).then(result => {
    console.log(JSON.parse(result.body));
  });
  console.log("--- End of Local Test ---");
}

そして,package.jsonstartスクリプトを追加します.

"scripts": {
  "start": "ts-node src/index.ts",
  "build": "..."
},

npm startコマンドでローカル実行できます.

付録2:外部ライブラリを使用したい

例えばaxiosを使って外部APIを叩く場合,まずはライブラリをインストールします.

npm install axios
npm install --save-dev @types/axios

あとはコード内でimportして使用するだけです.
今回のコードも以前のPython編と同じくピカチュウの名前を図鑑ナンバーからpokeAPIで取得して返しているだけです.

import { APIGatewayProxyHandler } from 'aws-lambda';
import axios from 'axios';

// PokeAPI のレスポンス型定義
interface PokemonResponse {
  name: string;
  id: number;
}

export const handler: APIGatewayProxyHandler = async (event, context) => {
    const response = await axios.get<PokemonResponse>('https://pokeapi.co/api/v2/pokemon/25');
    return {
        statusCode: 200,
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
        message: response.data.name,
        }),
    };
};

esbuildがビルド時にaxiosのコードもまとめてdist/index.jsにバンドルしてくれるため,ymlファイルを変更する必要はありません.esbuildめっちゃ便利...

おわりに

今回は,新しく提供が開始されたGitHub Actions (aws-actions/aws-lambda-deploy) を使って,TypeScriptで記述したAWS Lambda関数をデプロイする方法を紹介しました.

従来,TypeScriptでのLambda開発はトランスパイルやバンドルの設定が手間に感じられることがありましたが,esbuildのようなモダンなツールと新しいGitHub Actionsを組み合わせることで,CI/CDパイプラインの構築が非常にシンプルかつ高速になりました.

静的型付けの恩恵を受けながら,インフラ管理のコストを抑え,コードの変更を即座に反映できるこの方法は,あらゆる規模のプロジェクトで強力な選択肢になるはずです.

最後までお読みいただき、ありがとうございました.

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?