Serverless Flamework ことはじめ

Lambdaを学習するにあたり、Serverless Flameworkを利用したため、使い方について整理しました。

## Serverless Flameworkとは
一言で言うと、サーバレスアプリケーションの構成管理やデプロイのためのOSSツールです。

https://www.serverless.com/

AWS、Azure、Google Cloudといったクラウドサービスに対応しており、豊富なテンプレートも提供されています。

本記事では、AWSのCloud9を利用し、設定を進めます。


## インストール

Node.jsのv12以上が必要となるため、事前に公式サイトよりインストールしておきます。

Serverless Frameworkはnpmのパッケージとして公開されており、ターミナルで以下のコマンドを入力しまするとインストールできます。
```
> npm install -g serverless
# @を付けることで特定のバージョンの指定が可能
```

インストールしたslsのバージョンを確認します。
```
> serverless -v
# serverlessはslsと省略表記可能
```

## プロジェクト作成
Serverless Frameworkでは開発環境や用途に応じたテンプレートが公開されています。テンプレートは[こちら](https://www.serverless.com/framework/docs/providers/aws/cli-reference/create/)で確認可能です。

```
> serverless create --template <テンプレート名>
```

今回はNode.js対応の「aws-nodejs-ecma-script」を利用します。

プロジェクト作成時に、各設定ファイルが自動的に作成されます。（テンプレートによってファイルの種類は異なります）
```
.
├── first.js
├── package.json
├── second.js
├── serverless.yml
└── webpack.config.js
```

主なファイルの中身を見てみます。

**serverless.yml**
メインの設定ファイルです。サービスの名前、デプロイ先のAWSリージョン、Lambda関数の設定、イベントソースの設定(API Gatewayなど)、リソースの設定などを記述します。


```
service:
  name: environment
# app and org for use with dashboard.serverless.com
#app: your-app-name
#org: your-org-name
frameworkVersion: "3"

# Add the serverless-webpack plugin
plugins:
  - serverless-webpack

provider:
  name: aws
  runtime: nodejs18.x

functions:
  first:
    handler: first.hello
  second:
    handler: second.hello
    events:
      - httpApi:
          method: get
          path: /second

```

|項目|説明|
|---|---|
|service|デプロイするサービス名|
|framework Version|フレームワークのバージョン|
|plugins |特定の機能拡張|
|provider|アカウントの情報（CSP、リージョン、ステージ、認証プロファイル、ランタイムなど）|
|functions|デプロイする関数（関数名、ハンドラ、メモリサイズ、タイムアウト時間など）|
|resources|AWSリソースの定義（CFnと同じ構文）|

デフォルトの状態でfunctionsに着目すると、「first.hello」と「second.hello」のハンドラが定義されています。後者については、API GatewayへのGETリクエストを受け取るよう設定されています。

**first.js**
Lambda関数のコードを記述するファイルです。デフォルトでは `hello` という関数が定義されています。

```
export const hello = (event, context, callback) => {
  const p = new Promise((resolve) => {
    resolve('success');
  });
  p.then(() =>
    callback(null, {
      message: 'Go Serverless Webpack (Ecma Script) v1.0! First module!',
      event,
    })
  ).catch((e) => callback(e));
};
```
関数はPromiseベースの構造になっており、Promiseの成功/失敗に応じて異なる結果をLambdaの呼び出し元に返しています。


**second.js**
first.jsと似たような構造をしていますが、HTTP APIゲートウェイのリクエストに対するレスポンスを生成するように設計されています。
```
export const hello = (event, context, cb) => {
  const p = new Promise((resolve) => {
    resolve('success');
  });
  const response = {
    statusCode: 200,
    body: JSON.stringify(
      {
        message: 'Go Serverless Webpack (Ecma Script) v1.0! Second module!',
        input: event,
      },
      null,
      2
    ),
  };
  p.then(() => cb(null, response)).catch((e) => cb(e));
};
```

**package.json**
Node.jsアプリケーションの依存関係を管理するファイルです。プロジェクトで使用する外部ライブラリなどをここに記述します。
```
{
  "name": "environment",
  "version": "1.0.0",
  "description": "Serverless webpack example using ecma script",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "devDependencies": {
    "@babel/core": "^7.11.1",
    "@babel/preset-env": "^7.11.0",
    "babel-loader": "^8.1.0",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-polyfill": "^6.23.0",
    "babel-preset-env": "^1.6.0",
    "serverless-webpack": "^5.3.1",
    "webpack": "^4.35.2"
  },
  "author": "The serverless webpack authors (https://github.com/elastic-coders/serverless-webpack)",
  "license": "MIT"
}
```

このようにServerless Frameworkでは、設定ファイルやコードの初期テンプレートが自動生成されるので、すぐにアプリケーション開発を始められるのが特徴です。​​​​​​​​​​​​​​​​
基本はserverless.ymlを編集しつつ、個別の関数ファイルを作成する流れとなります。

## デプロイ
設定が終わったら、次のコマンドでAWS上にアプリケーションをデプロイします。

```
serverless deploy -v --stage <ステージ名> --region <リージョン名>
```
-vオプションをつけることで、デプロイの途中経過がターミナルで確認できます。
またデプロイ先の環境を指定する`--stage`と`--region`については未入力の場合、デフォルトに従い`dev`ステージ、`us-east`リージョンにデプロイされるため注意が必要です。serverless.ymlの`provider`内で指定することも可能です。

デプロイが成功すると、AWS上にLambda関数やAPI Gatewayリソースなどが作成されます。
AWSマネジメントコンソールから、CloudFormationを開くと新たにスタックが作成されていることが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3665293/6b97902d-eb3d-8c65-4adb-208fc154210d.png)

なお設定保存用にS3バケットも作成されていますので、誤って削除しないよう注意が必要です。

## 関数の実行とログの確認
デプロイ後は、次のコマンドでLambda関数を直接実行できます。

```
serverless invoke --function <関数名>
```
試しにfirst.js(関数名:first)を実行すると以下のような結果が得られます。
```
Running "serverless" from node_modules
{
    "message": "Go Serverless Webpack (Ecma Script) v1.0! First module!",
    "event": {}
}
```

また、次のコマンドでログを確認できます。

```
serverless logs --function <関数名>
```

デプロイしたアプリケーションを削除したい場合は、以下のコマンドを入力します。
```
serverlesss remove
```

## おわりに
Serverless Frameworkを利用することのメリットの詳細な設定方法は[公式ドキュメント](https://www.serverless.com/framework/docs)にまとめられています。
AWS SAMと比較し、API Gatewayなどのリソース定義を簡略化することができるため、サーバレスアプリケーションを効率的に開発できるのではないでしょうか。

## 参考
* [Serverless Frameworkの使い方まとめ](https://serverless.co.jp/blog/025/)
* [Serverless Framework はじめの一歩](https://makky12.hatenablog.com/entry/2020/12/18/070000)