Serverless の TypeScript テンプレートを使って Lambda 関数をデプロイする

Lambda をはじめサーバーレスアプリケーションの管理ができる Serverless Framework
TypeScript を使ってデプロイして動作確認まで試してみました。

TypeScript テンプレートを使うと関数を TypeScript で書けるのはもちろん、
YAML で書いていた構成設定ファイルも TypeScript で書けるのは大きなメリットです!

www.serverless.com

Node.js のバージョン確認

$ node -v
v12.18.4

Serverless をインストール

$ npm install -g serverless

serverless もしくは省略した sls でコマンドが使えるようになるので、バージョンを確認します。

$ sls --version
Framework Core: 2.8.0
Plugin: 4.1.1
SDK: 2.3.2
Components: 3.2.7

それぞれなんのバージョンなのか?

Framework Core: Serverless 本体のバージョン

Plugin: @serverless/enterprise-plugin のバージョン

Serverless のエンタープライズ版を使う時に有効にするプラグインです。
エンタープライズ版は Serverless を使ってデプロイしたアプリケーションの監視・テストなどができるサービスです。

SDK: @serverless/platform-sdk のバージョン

各プラットフォーム(AWS, GCP など)とのインターフェースとなる SDKです。
今後は廃止予定(今後はバグ修正のみ)の SDKで@serverless/platform-clientへ統合される予定です。

Components: @serverless/components のバージョン

sls --version コマンドの実装箇所はこちら

github.com

Serverless プロジェクトの作成

sls create コマンドを使ってプロジェクトを作成します。

-t にはテンプレート名を指定します。今回は AWS Lambda の TypeScript テンプレートを使うので aws-nodejs-typescriptを指定します。

-p にはプロジェクト名を指定します。

$ sls create -t aws-nodejs-typescript -p example-project

Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/path/example-project"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v2.8.0
 -------'

Serverless: Successfully generated boilerplate for template: "aws-nodejs-typescript"

プロジェクトの作成が完了したら、必要なパッケージをインストールします。

$ cd example-project

$ npm install

つづいて生成されたファイルを確認します。

$ ls | xargs basename

handler.ts
package.json
serverless.ts
tsconfig.json
webpack.config.js

serverless.ts の確認

注目箇所はproviderfunctionsの 2 点です。

providerには「利用するサービスは AWS で Node.js v12 を使う」

functions には「handler.ts の hello 関数を hello という名称の Lambda 関数として使い、API Gateway 経由で /hello に GET リクエストでアクセスできるようにする」

といった内容が書かれています。

TypeScript で書くことで必須項目の有無、型による制限などの恩恵が受けられます。

import type { Serverless } from 'serverless/aws';

const serverlessConfiguration: Serverless = {
  service: {
    name: 'example-project',
    // app and org for use with dashboard.serverless.com
    // app: your-app-name,
    // org: your-org-name,
  },
  frameworkVersion: '2',
  custom: {
    webpack: {
      webpackConfig: './webpack.config.js',
      includeModules: true,
    },
  },
  // Add the serverless-webpack plugin
  plugins: ['serverless-webpack'],
  provider: {
    name: 'aws',
    runtime: 'nodejs12.x',
    apiGateway: {
      minimumCompressionSize: 1024,
    },
    environment: {
      AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1',
    },
  },
  functions: {
    hello: {
      handler: 'handler.hello',
      events: [
        {
          http: {
            method: 'get',
            path: 'hello',
          },
        },
      ],
    },
  },
};

module.exports = serverlessConfiguration;

handler.ts の確認

hello 関数が生成され デフォルト では APIGatewayProxyHandler が指定されており、
API Gateway + Lambda の構成を前提としたコードが生成されます。

S3 からのイベントを受け取る関数の場合は S3Handler
DynamoDB からのイベントを受け取る関数の場合は DynamoDBStreamHandler など
関数の目的に合わせた型を指定することで event オブジェクトで型情報が使えるようになります。

import { APIGatewayProxyHandler } from 'aws-lambda';
import 'source-map-support/register';

export const hello: APIGatewayProxyHandler = async (event, _context) => {
  return {
    statusCode: 200,
    body: JSON.stringify(
      {
        message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!',
        input: event,
      },
      null,
      2
    ),
  };
};

ローカル環境で動作確認

sls invoke コマンドを使って、ローカル環境で関数を実行して動作確認をします。

sls invoke local でローカル環境で関数を実行できます。

-f には実行対象の関数名を指定します。

$ sls invoke local -f hello

Serverless: Bundling with Webpack...
Time: 153ms
Built at: 2020-10-23 22:32:09
     Asset      Size   Chunks             Chunk Names
handler.js  6.29 KiB  handler  [emitted]  handler
Entrypoint handler = handler.js
[./handler.ts] 316 bytes {handler} [built]
[source-map-support/register] external "source-map-support/register" 42 bytes {handler} [built]
{
    "statusCode": 200,
    "body": "{\n  \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!\",\n  \"input\": \"\"\n}"
}

AWS にデプロイ

sls deploy コマンドを使って関数を AWS にデプロイします。

$ sls deploy

~~~~~ 省略 ~~~~~
Serverless: Stack create finished...
Service Information
service: example-project
stage: dev
region: ap-northeast-1
stack: example-project-dev
resources: 8
api keys:
  None
endpoints:
  GET - https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello
functions:
  hello: example-project-dev-hello
layers:
  None

Serverless: Stack update finished... が表示されたらデプロイ完了です!

デプロイされた関数の動作確認

sls invokelocal を付けないと AWS にデプロイされた関数が実行されます。

$ sls invoke -f hello

{
    "statusCode": 200,
    "body": "{\n  \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!\",\n  \"input\": {}\n}"
}

デプロイログの endpoints に表示されている URL でアクセス可能です。

$ curl -X GET https://xxxxx.execute-api.us-east-1.amazonaws.com/dev/hello

{
  "message": "Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!",
  "input": {
    ~~~~~ 省略 ~~~~~
  }
}

以上で、Serverless Framework で TypeScript テンプレートを使った Lambda 関数のデプロイは完了です!

おまけ

他に使えるテンプレートは?

Serverless Framework で使えるテンプレートこちらです。

serverless/lib/plugins/create/templates at master · serverless/serverless · GitHub

GCP や Azure のテンプレートもあります。

TypeScript の型定義はどこにあるの?

Serverless Framework の本体には型定義は入っておらず、TypeScript の型定義は @type/serverless に存在しています。

www.npmjs.com

ほとんどの型が網羅されていますが、用途として少ない型はないことも。
必要であればコントリビュートして追加することが可能です。