😄

AWS SAM CLIのTypescript (esbuild) サポートがGAした話

2022/09/13に公開

2022-02-25のTypescriptサポートのベータ版アナウンスから約半年経って、2022-09-02にリリースされたv1.56.0でついにTypescript (esbuild) のサポートがGA (General Availability) しました!
https://github.com/aws/aws-sam-cli/releases/tag/v1.56.0

早速触ってみたので記事にしたいと思います!

2022/9/21追記:
9/1にAWSよりGAのアナウンスが出ていました。
https://aws.amazon.com/about-aws/whats-new/2022/09/aws-sam-cli-esbuild-support-available/?nc1=h_ls

前提知識

この記事では、以下の経験・知識がある前提で作成しています。

  • Typescriptのビルドに関する知識
  • Typescriptに関する基本的な知識
  • AWS SAM CLIを使ったLambda関数の作成

また、実行環境は以下のとおりです。

  • macOS Monterey
  • MacBook Air (M1, 2020)
  • Homebrew 3.6.1
  • Docker Desktop 4.12.0 (85629)

さらに、AWSのクレデンシャルの設定 (~/.aws/credentials) の設定が完了していることを想定しています。

やってみること

AWS SAM CLIのGoのhello-goテンプレートのTypescriptバージョンを作成してみます。

やってみた

準備

まず、AWS SAM CLIを最新版にアップデートします。
もし、aws-sam-cliとDocker Desktopのインストールが済んでいなければ、こちらを元にインストールしてください。

brew upgrade aws-sam-cli
sam --version
# 1.56.0以上であることをチェック

プロジェクトの作成

次に、sam initでプロジェクト(雛形)を作成します。

sam init

この時、いくつか質問されるので、以下の通りに答えます。
※AWS SAM CLI version 1.56.1の場合。それ以上の場合は設問の順番・入力する番号が異なる可能性があります。適宜読替えてください。

You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.

Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1

Choose an AWS Quick Start application template
        1 - Hello World Example
        2 - Multi-step workflow
        3 - Serverless API
        4 - Scheduled task
        5 - Standalone function
        6 - Data processing
        7 - Infrastructure event management
        8 - Lambda EFS example
        9 - Machine Learning
Template: 1

Use the most popular runtime and package type? (Python and zip) [y/N]: 

Which runtime would you like to use?
        1 - dotnet6
        2 - dotnet5.0
        3 - dotnetcore3.1
        4 - go1.x
        5 - graalvm.java11 (provided.al2)
        6 - graalvm.java17 (provided.al2)
        7 - java11
        8 - java8.al2
        9 - java8
        10 - nodejs16.x
        11 - nodejs14.x
        12 - nodejs12.x
        13 - python3.9
        14 - python3.8
        15 - python3.7
        16 - python3.6
        17 - ruby2.7
        18 - rust (provided.al2)
Runtime: 10

What package type would you like to use?
        1 - Zip
        2 - Image
Package type: 1

Based on your selections, the only dependency manager available is npm.
We will proceed copying the template using npm.

Select your starter template
        1 - Hello World Example
        2 - Hello World Example TypeScript
Template: 2

Would you like to enable X-Ray tracing on the function(s) in your application?  [y/N]: 

Project name [sam-app]: sam-app-typescript

Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)

    -----------------------
    Generating application:
    -----------------------
    Name: sam-app4
    Runtime: nodejs16.x
    Architectures: x86_64
    Dependency Manager: npm
    Application Template: hello-world-typescript
    Output Directory: .
    
    Next steps can be found in the README file at ./sam-app4/README.md
        

    Commands you can use next
    =========================
    [*] Create pipeline: cd sam-app4 && sam pipeline init --bootstrap
    [*] Validate SAM template: sam validate
    [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch

ビルドとデプロイができるか確認

早速、sam build -usam deployを実行して、Lambda関数にアクセスできることを確認しましょう!

cd sam-app-typescript
sam build -u

# 出力 ※一部/path/toに変更
Starting Build inside a container
Your template contains a resource with logical ID "ServerlessRestApi", which is a reserved logical ID in AWS SAM. It could result in unexpected behaviors and is not recommended.
Building codeuri: /path/to/sam-app-typescript/hello-world runtime: nodejs16.x metadata: {'BuildMethod': 'esbuild', 'BuildProperties': {'Minify': True, 'Target': 'es2020', 'EntryPoints': ['app.ts']}} architecture: x86_64 functions: HelloWorldFunction

Fetching public.ecr.aws/sam/build-nodejs16.x:latest-x86_64 Docker container image......
Mounting /path/to/sam-app-typescript/hello-world as /tmp/samcli/source:ro,delegated inside runtime container

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
[*] Deploy: sam deploy --guided
        
Running NodejsNpmEsbuildBuilder:CopySource
Running NodejsNpmEsbuildBuilder:NpmInstall
Running NodejsNpmEsbuildBuilder:EsbuildBundle

ビルドが成功すると、プロジェクトディレクトリの.aws-sam/build/HelloWorldFunction以下にapp.jsが作成されているので見てみましょう。

cat .aws-sam/build/HelloWorldFunction/app.js

結合され、minifyされたjavascriptが確認できるはずです。
さて、このjavascriptをsam deploy --guidedを使ってデプロイしてみましょう。
※sam deployの初回実行時は、samconfig.tomlがまだないため、--guidedを付けて実行する必要して各質問に答える必要があります。二回目以降は--guidedをつける必要はありません。

sam deploy --guided
# 出力
Configuring SAM deploy
======================

        Looking for config file [samconfig.toml] :  Not found

        Setting default arguments for 'sam deploy'
        =========================================
        Stack Name [sam-app]: sam-app-typescript
        AWS Region [ap-northeast-1]: 
        #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
        Confirm changes before deploy [y/N]: 
        #SAM needs permission to be able to create roles to connect to the resources in your template
        Allow SAM CLI IAM role creation [Y/n]: 
        #Preserves the state of previously provisioned resources when an operation fails
        Disable rollback [y/N]: 
        HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
        Save arguments to configuration file [Y/n]: 
        SAM configuration file [samconfig.toml]: 
        SAM configuration environment [default]: 
	
<>

Outputs                                                                                                                                                                                             
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldFunctionIamRole                                                                                                                                                       
Description         Implicit IAM Role created for Hello World function                                                                                                                              
Value               arn:aws:iam::************:role/sam-app-typescript-HelloWorldFunctionRole-***********                                                                                          

Key                 HelloWorldApi                                                                                                                                                                   
Description         API Gateway endpoint URL for Prod stage for Hello World function                                                                                                                
Value               https://*********.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/                                                                                                         

Key                 HelloWorldFunction                                                                                                                                                              
Description         Hello World Lambda Function ARN                                                                                                                                                 
Value               arn:aws:lambda:ap-northeast-1:************:function:sam-app-typescript-HelloWorldFunction-************                                                                          
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - sam-app-typescript in ap-northeast-1

デプロイができたら、早速Outputに出力されたエンドポイントにアクセスしてみましょう。

curl https://*********.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/

{"message":"hello world"}と表示されれば、無事デプロイ成功です!🥳🥳🥳

app.tsを修正

さて、ここまででプロジェクトの初期状態でビルドとデプロイができることを確認できました。
次は、実際にapp.tsを編集してみて、ビルドとデプロイができるか確認してみましょう。

まず、コードを修正していくにあたり編集に必要なパッケージをインストールしましょう。

cd hello-world
npm install
npm install --save node-fetch

次に、app.tsを以下のように編集して保存します。

import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import fetch from 'node-fetch';

export const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
    const res = await fetch('https://checkip.amazonaws.com');

    if (res.status !== 200) {
        return {
            statusCode: res.status,
            body: 'Non 200 Response found',
        };
    }

    const raw = await res.text();
    const ip = raw.trim();

    if (ip.length === 0) {
        return {
            statusCode: 504,
            body: 'No IP in HTTP response',
        };
    }

    const response: APIGatewayProxyResult = {
        statusCode: res.status,
        body: 'Hello, ' + ip,
    };

    return response;
};

続いては、変更したapp.tsをビルドしてデプロイしていきます。

ビルドとデプロイ

sam build -uでもう一度ビルドします。

cd ..
sam build -u

一旦、ローカルでlambda関数を実行してみます。Hello, <IPアドレス>が表示されれば成功です。

sam local invoke

続いてsam deployでデプロイします。
この時、samconfig.tomlはすでにあるはずなので、--guidedは不要です。

sam deploy

デプロイが完了したら、もう一度curlでアクセスしてみましょう。Hello, <IPアドレス>が表示されれば成功です!🥳🥳🥳

curl https://*********.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/

所感

今までTypescriptを使ってlambda関数を作るには、serverless frameworkを使うか、AWS SAM CLIのnodejsテンプレートを改造して、Typescriptに対応するしかありませんでした。
今回、AWS SAM CLIのTypescript (esbuild) サポートがGAしたことにより、AWS SAMを使って簡単にTypescriptを使ったlambda関数の作成ができるようになりました。

今後は、フロントエンドとlambda関数をTypescriptで統一して何かしらWebアプリを作れないか模索してこうと思っています。

以上、長々とお付き合いいただきありがとうございました!

では、また

Discussion