Serverless Frameworkで複数のLambdaを管理する

## やったこと
- Serverless Framework を使って、API Gateway + LambdaでAPIを作りました。
  - 一つのAPI Gatewayでリソースが違うpathに対してLambdaを振り分けるようにした。  
`https://hoge/v1/fun1` にリクエストがきたら Lambda1 をinvokeして  
`https://hoge/v1/fun2` にリクエストがきたら Lambda2 をinvokeする  
みたいな感じです。

### 追記

validationもしてみました。
[express-validatorでvalidationしてみた。](https://qiita.com/Ntakato/items/df77326ee9d188cef837)


## Serverless Framework
https://www.serverless.com/open-source/
> Serverless Framework Open Source lets you develop and deploy serverless applications to AWS, Azure, GCP & more. Use it with Pro for full serverless application lifecycle management.

Serverless Frameworkはサーバーレスアプリケーションの開発、AWS,Azure,GCPなどへのデプロイができるフレームワークです。

今回はAWSへのデプロイをします。

API Gateway + LambdaでAPIを作るのはよくある構成なので、フレームワークでパパッとできるのは助かるところです。

## やってみる

Serverless Frameworkの導入
https://www.serverless.com/framework/docs/getting-started/

```shell
$ npm install -g serverless
```

AWS のcredential設定
https://www.serverless.com/framework/docs/providers/aws/guide/credentials/

```sh
$ serverless config credentials --provider provider --key key --secret secret
```

`sls create`をするとServerless Frameworkが用意しているテンプレートが作成されますが
今回はserverless-expressを使うので、このテンプレートは使わずに、
https://zenn.dev/yuta_saito/articles/8b543a1957c375593ee5
に書いてあるものを参考にして作りました。

lambda.jsが書いてある通りでは動かなかったので、その部分については
https://github.com/vendia/serverless-express#minimal-lambda-handler-wrapper を参考にすれば動きました。

単一のLambdaを作るのはこれでいいでしょう。
簡単ですね。

複数のLambdaを作りたいときは`serverless.yml`のfunctionsを以下のようにすることで複数のlambdaを追加することができるらしい
https://www.serverless.com/framework/docs/providers/aws/guide/functions/

```yml
# serverless.yml

service: myService

provider:
  name: aws
  runtime: nodejs12.x

functions:
  functionOne:
    handler: handler.functionOne
    description: optional description for your Lambda
  functionTwo:
    handler: handler.functionTwo
  functionThree:
    handler: handler.functionThree
```

ということで、最終的なserverless.ymlは以下

```yml
service: serverless-express-test

provider:
  name: aws
  runtime: nodejs12.x
  region: ap-northeast-1

package:
  exclude:
    - .git/**
    - test/**
    - README.md

functions:
  serverlessTest1:
    handler: lambda.handler1
    events:
      - http: ANY /v1/fun1
      - http: 'ANY /v1/fun1/{proxy+}'
  serverlessTest2:
    handler: lambda.handler2
    events:
      - http: ANY /v1/fun2
      - http: 'ANY /v1/fun2/{proxy+}'
  ```

ファイル構造はこんな感じになりました。

```sh
.
├── README.md
├── functions
│   ├── function1
│   │   ├── app.js
│   │   ├── local-app.js
│   │   └── routes
│   │       └── router.js
│   └── function2
│       ├── app.js
│       ├── local-app.js
│       └── routes
│           └── router.js
├── lambda.js
├── package.json
├── serverless.yml
└── yarn.lock
```



で`lambda.js`が以下のようになりました。

```js
const serverlessExpress = require('@vendia/serverless-express')
const lambda1 = require('./functions/function1/app')
const lambda2 = require('./functions/function2/app')

exports.handler1 = serverlessExpress({ app: lambda1 }).handler

exports.handler2 = serverlessExpress({ app: lambda2 }).handler
```

一応最終的なものはGitHubにあげておきます。
https://github.com/Ntakato/slsTutorial/tree/f1b17d6bd222cacf8d01ba2561c30171ba148306

これで

```sh
$ sls deploy
```

をすれば、AWSにAPI GatewayとLambdaが2つ作られます。

## 感想

Serverless Frameworkを使えばAPI Gateway + LambdaでAPIを簡単にぱぱっと作れることがわかりました。
便利ですね。
ただ、この方法で複数のLambdaを作ると、Lambda1にLambda2のコードも含んでしまうなぁ。

### 追記

```yml
# serverless.yml
...
package:
  exclude:
    - .git/**
    - test/**
    - README.md
    - functions/**
...
functions:
  serverlessTest1:
    handler: functions/function1/lambda.handler
    package:
      include: 
        - functions/function1/**
      individually: true 
    events:
      - http: ANY /fun1/v1/user
...
```

みたいな感じでpackageでexcludeして、個別にlambdaに必要な部分をincludeすれば必要なところだけlambdaのコードとしてアップロードできました。