aws-nodejs-typescriptのテンプレートを使ってみる(serverless v3)

この記事は、[Ateam Finergy Inc\.× Ateam CommerceTech Inc\.× Ateam Wellness Inc\.のカレンダー \| Advent Calendar 2022](https://qiita.com/advent-calendar/2022/finergy-commerce-tech-wellness) の15日目の記事になります。

本日は、@tommy1038が担当いたします。

## はじめに

今年の始めごろに下記の記事を書いてみたのですが、その後すぐに、serverless v3がリリースされました。

https://qiita.com/tommy1038/items/a97dbbd3ef6c08fc5bd7

https://github.com/serverless/serverless/releases/tag/v3.0.0

serverless v3へのアップデートガイドはこちら(https://www.serverless.com/framework/docs/guides/upgrading-v3)

業務で使用しているサービスも、serverless v3に対応していきましたが、公式のテンプレはどう変わったのかなと思ったので、前回の記事をアップデートしていければと思います。

## 事前準備

実行環境としては、以下のバージョンで実施しました。
ただserverlessを試してみたい、という方であれば、こちらからすぐ試せそうです。(https://github.com/serverless/serverless#quick-start)

```
❯ node -v
v18.12.1

❯ npm --version
8.19.3

❯ serverless --version
Framework Core: 3.25.1
Plugin: 6.2.2
SDK: 4.3.2

❯ aws --version
aws-cli/2.9.6 Python/3.11.0 Darwin/21.6.0 source/x86_64 prompt/off
```

AWSの認証情報をセットアップします。
aws configure コマンドを実行して、プロンプトに従えばOKです。

```
❯ aws configure
AWS Access Key ID [None]: your_access_key_id
AWS Secret Access Key [None]: your_secret_access_key
Default region name [None]:
Default output format [None]:
```

アクセスキー ID とシークレットアクセスキーがない場合は、
[設定の基本 \- AWS Command Line Interface](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-creds)のアクセスキーIDとシークレットアクセスキーのところで作成の手順が記載されていますので、そちらで作成してから登録してください。

## サービスの作成

https://www.serverless.com/framework/docs/providers/aws/cli-reference/create

上記を参考に、サービスを作成していきます。

### `--template`オプションで作成する

現在利用できるテンプレート一覧がこのようになっています。

- aws-clojurescript-gradle
- aws-clojure-gradle
- aws-nodejs
- aws-nodejs-typescript
- aws-alexa-typescript
- aws-nodejs-ecma-script
- aws-python
- aws-python3
- aws-ruby
- aws-provided
- aws-kotlin-jvm-maven
- aws-kotlin-jvm-gradle
- aws-kotlin-nodejs-gradle
- aws-groovy-gradle
- aws-java-maven
- aws-java-gradle
- aws-scala-sbt
- aws-csharp
- aws-fsharp
- aws-go
- aws-go-dep
- aws-go-mod
- plugin

では、上記の`aws-nodejs-typescript`を使ってみます。

```sh
❯ serverless create --template aws-nodejs-typescript --path aws-nodejs-typescript-1

✔ Project successfully created in "aws-nodejs-typescript-1" from "aws-nodejs-typescript" template (7s)

❯ tree .
.
├── README.md
├── package.json
├── serverless.ts
├── src
│   ├── functions
│   │   ├── hello
│   │   │   ├── handler.ts
│   │   │   ├── index.ts
│   │   │   ├── mock.json
│   │   │   └── schema.ts
│   │   └── index.ts
│   └── libs
│       ├── api-gateway.ts
│       ├── handler-resolver.ts
│       └── lambda.ts
├── tsconfig.json
└── tsconfig.paths.json

4 directories, 13 files
```

serverless v3で実行したので、[examples/aws\-node\-typescript at v3 · serverless/examples](https://github.com/serverless/examples/tree/v3/aws-node-typescript)が適用されるのかな思いましたが、[examples/legacy/aws\-nodejs\-typescript at v3 · serverless/examples](https://github.com/serverless/examples/tree/v3/legacy/aws-nodejs-typescript)が適用されているっぽいです。

このテンプレだと、年初に書いた[aws\-nodejs\-typescriptのテンプレートを使ってみる#プロジェクトの作成](https://qiita.com/tommy1038/items/a97dbbd3ef6c08fc5bd7#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90) で確認したいことは事足りそうでした。

今回は、v3のテンプレを適用させたいので、公式のテンプレをURLで指定したいと思います。

### `--template-url`オプションで作成する

```sh
❯ serverless create --template-url https://github.com/serverless/examples/tree/v3/aws-node-typescript --path aws-nodejs-typescript-2

✔ Project successfully created in "aws-nodejs-typescript-2" (5s)

❯ tree .
.
├── README.md
├── handler.ts
├── package.json
└── serverless.yml

0 directories, 4 files
```

無事、v3で更新されたテンプレートを適用できたようです。

実際のテンプレートのコードはこちらです。

https://github.com/serverless/examples/tree/v3/aws-node-typescript

コードを細かくみていくことはしませんが、以前のテンプレだと機能がもりもりで読み解いていかないといけないところから、ミニマム実装になり非常にわかりやすくなっていました。たとえば、以前であればエンドポイントが自動で作成されていましたが、今回はなくなっているみたいです。また、細かいですが、`serverless.ts`から`serverless.yml`になっていますね。

エンドポイント作成したりするテンプレートとしては、[aws-node-http-api-typescript](https://github.com/serverless/examples/tree/v3/aws-node-http-api-typescript)を使えば、エンドポイント周りの作成の際、うまくお作法に則って作れそうですね。


### ローカル実行

さて、では実際にローカルで実行してみましょう。

```
❯ yarn install
yarn install v1.22.19
warning package.json: No license field
info No lockfile found.
warning aws-nodejs-typescript-2: No license field
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
✨  Done in 7.65s.

❯ serverless invoke local --function hello
{
    "message": "Go Serverless v3! Your function executed successfully!",
    "input": ""
}
```

`handler.ts`の`hello`ファンクションが正しく呼び出されていることがわかります。

### デプロイ

では、実際にawsにデプロイしたいと思いますが、リージョンを`ap-northeast-1`にして、デプロイできるように追記します。

```serverless.yml
service: aws-nodejs-typescript-2
frameworkVersion: '3'

provider:
  name: aws
  runtime: nodejs14.x
  region: ap-northeast-1 # 追記

functions:
  hello:
    handler: handler.hello

plugins:
  - serverless-esbuild
```

では、デプロイします。（ログを出すために、`--verbose`をつけています。）

```
❯ serverless deploy --verbose

Deploying aws-nodejs-typescript-2 to stage dev (ap-northeast-1)

Packaging
Compiling to node14 bundle with esbuild...
Compiling with concurrency: Infinity
Compiling completed.
Zip service aws-nodejs-typescript-2 - 688.00 B [50 ms]
Retrieving CloudFormation stack
Creating CloudFormation stack
Creating new change set
Waiting for new change set to be created
Change Set did not reach desired state, retrying
Executing created change set
  CREATE_IN_PROGRESS - AWS::CloudFormation::Stack - aws-nodejs-typescript-2-dev
  CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
  CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
  CREATE_COMPLETE - AWS::S3::Bucket - ServerlessDeploymentBucket
  CREATE_IN_PROGRESS - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy
  CREATE_IN_PROGRESS - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy
  CREATE_COMPLETE - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy
  CREATE_COMPLETE - AWS::CloudFormation::Stack - aws-nodejs-typescript-2-dev
Uploading
Uploading CloudFormation file to S3
Uploading State file to S3
Uploading service aws-nodejs-typescript-2.zip file to S3 (688 B)
Updating CloudFormation stack
Creating new change set
Waiting for new change set to be created
Change Set did not reach desired state, retrying
Executing created change set
  UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - aws-nodejs-typescript-2-dev
  CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
  CREATE_IN_PROGRESS - AWS::Logs::LogGroup - HelloLogGroup
  CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
  CREATE_IN_PROGRESS - AWS::Logs::LogGroup - HelloLogGroup
  CREATE_COMPLETE - AWS::Logs::LogGroup - HelloLogGroup
  CREATE_COMPLETE - AWS::IAM::Role - IamRoleLambdaExecution
  CREATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
  CREATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction
  CREATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction
  CREATE_IN_PROGRESS - AWS::Lambda::Version - HelloLambdaVersion****************************************
  CREATE_IN_PROGRESS - AWS::Lambda::Version - HelloLambdaVersion****************************************
  CREATE_COMPLETE - AWS::Lambda::Version - HelloLambdaVersion****************************************
  UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - aws-nodejs-typescript-2-dev
  UPDATE_COMPLETE - AWS::CloudFormation::Stack - aws-nodejs-typescript-2-dev
Retrieving CloudFormation stack
Removing old service artifacts from S3

✔ Service deployed to stack aws-nodejs-typescript-2-dev (110s)

functions:
  hello: aws-nodejs-typescript-2-dev-hello (688 B)

Stack Outputs:
  HelloLambdaFunctionQualifiedArn: arn:aws:lambda:ap-northeast-1:************:function:aws-nodejs-typescript-2-dev-hello:3
  ServerlessDeploymentBucketName: aws-nodejs-typescript-2-serverlessdeploymentbuck-************
```

ではファンクションの実行と、デプロイした情報を見てみましょう。

```
❯ serverless invoke --function hello
{
    "message": "Go Serverless v3! Your function executed successfully!",
    "input": {}
}

❯ serverless info
service: aws-nodejs-typescript-2
stage: dev
region: ap-northeast-1
stack: aws-nodejs-typescript-2-dev
functions:
  hello: aws-nodejs-typescript-2-dev-hello
```

ここで念の為確認ですが、`serverless info`で示されていたり、先ほどのログにも

> Deploying aws-nodejs-typescript-2 to stage dev (ap-northeast-1)

と書いてあるので、stage名が`dev`として登録されています。（`serverless.yml`に明記した方が混乱を防げると思います。）

これと、serverless v3で導入された、`stage parameters`を用いることで、`dev`、`staging`、`production`などの環境の変数定義と出し分けがしやすくなります。（参考: [Serverless Framework v3新機能のStage Parameters紹介 \| 豆蔵デベロッパーサイト](https://developer.mamezou-tech.com/blogs/2022/02/17/serverless-v3-stage-parameters/)）

https://www.serverless.com/blog/serverless-framework-v3-is-live

### node v18にアップデート

冒頭から記事を読み進めてきた方の中で、あれ？と違和感を覚えている人がおられると思いますが、僕はローカル環境で`node v18`にしていましたが、`serverless.yml`が`nodejs14.x`のままにしていたので、ちぐはぐな状態でした。

今年の11月に、aws lambdaがv18に対応しているので、nodejs v18に上げてしまいましょう。

https://aws.amazon.com/jp/about-aws/whats-new/2022/11/aws-lambda-support-node-js-18/


```serverless.yml
service: aws-nodejs-typescript-2
frameworkVersion: '3'

provider:
  name: aws
  runtime: nodejs18.x # v14->v18にアップデート
  stage: ${opt:stage, 'dev'} # デプロイ時に設定できるように設定。デフォルトでは'dev'とする
  region: ap-northeast-1

functions:
  hello:
    handler: handler.hello

plugins:
  - serverless-esbuild
```

```
❯ serverless deploy --stage dev --verbose

Deploying aws-nodejs-typescript-2 to stage dev (ap-northeast-1)

Packaging
Compiling to node18 bundle with esbuild...
Compiling with concurrency: Infinity
Compiling completed.
Zip service aws-nodejs-typescript-2 - 688.00 B [35 ms]
Retrieving CloudFormation stack
Uploading
Uploading CloudFormation file to S3
Uploading State file to S3
Uploading service aws-nodejs-typescript-2.zip file to S3 (688 B)
Updating CloudFormation stack
Creating new change set
Waiting for new change set to be created
Change Set did not reach desired state, retrying
Executing created change set
(中略)
Retrieving CloudFormation stack
Removing old service artifacts from S3

✔ Service deployed to stack aws-nodejs-typescript-2-dev (64s)

functions:
  hello: aws-nodejs-typescript-2-dev-hello (688 B)

Stack Outputs:
  HelloLambdaFunctionQualifiedArn: arn:aws:lambda:ap-northeast-1:************:function:aws-nodejs-typescript-2-dev-hello:4
  ServerlessDeploymentBucketName: aws-nodejs-typescript-2-serverlessdeploymentbuck-************

❯ serverless invoke --function hello
{
    "message": "Go Serverless v3! Your function executed successfully!",
    "input": {}
}
```

管理画面でも見てみましょう。（nodejs v14 -> v18に）

| nodejs v14 | nodejs v18 |
| --- | --- |
| ![スクリーンショット 2022-12-11 16.44.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153992/e0352534-98d9-ddc5-c66c-d06f949ab8f7.png) | ![スクリーンショット 2022-12-11 16.44.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153992/1dc598bc-dcc0-9528-eba4-f46ef3ab81a1.png) |

無事、v18にアップデートができているようです。

### yarn v3にアップデート

最後におまけですが、`yarn`をv3にしてみます。元々、自分の環境では、

```
❯ yarn -v
1.22.19
```

で、1系だったのでアップデートしてみます。

```
❯ rm -rf yarn.lock node_modules
❯ yarn set version berry
```

`.yarnrc.yml`の追記

```.yarnrc.yml
yarnPath: .yarn/releases/yarn-3.3.0.cjs
nodeLinker: node-modules #追加
```

`.gitginore`の追記

```.gitignore
# package directories
node_modules
.esbuild

# Serverless directories
.serverless

# yarn v3
.yarn/
!.yarn/releases/*
```

これで問題なく動作するか、確認してみます。

```
❯ yarn install
❯ serverless invoke local --function hello
{
    "message": "Go Serverless v3! Your function executed successfully!",
    "input": ""
}
```

問題なさそうでした。ちょっと細かいところは、他の方の記事を見たほうが良さそうです。ひとまず今回のアップデートはうまくいったように思います。

## サービスの削除

サービスは以下の形で削除できます。stage名はデフォルトで`dev`なのでなくても問題ありません。

```
❯ serverless remove --stage dev
```

## まとめ

今回、以前の記事のアップデートということで、serverless v3の環境下でテンプレートを実行してみました。以前は、機能がもりもりのテンプレートでしたが、今回はミニマムで必要な部分だけかいつまんで進めていけそうです。

## 参考リンク集

- [Serverless: Develop & Monitor Apps On AWS Lambda](https://www.serverless.com/)
- [serverless/serverless: ⚡ Serverless Framework – Build web, mobile and IoT applications with serverless architectures using AWS Lambda, Azure Functions, Google CloudFunctions & more\! –](https://github.com/serverless/serverless)
- 導入まわり
  - [Serverless Frameworkの使い方まとめ \| Serverless Operations](https://serverless.co.jp/blog/25/)
  - ↑前回も参考にさせていただきましたが、serverless v3の内容も加筆されている、すごい
- serverless v2 -> v3
  -  [Serverless Framework v2 から v3 の変更点まとめ \- サーバーワークスエンジニアブログ](https://blog.serverworks.co.jp/sls-v3-update-summary)
  - [ServerlessFramework V3 のメリット＆アップグレード方法、新機能のメリットをサーバーレスエキスパートが紹介します😎 \| Ragate ブログ](https://www.ragate.co.jp/blog/articles/12074)
  - [Serverless Framework v3新機能のStage Parameters紹介 \| 豆蔵デベロッパーサイト](https://developer.mamezou-tech.com/blogs/2022/02/17/serverless-v3-stage-parameters/)
- node v18
  - [AWS Lambda が Node\.js 18 のサポートを追加](https://aws.amazon.com/jp/about-aws/whats-new/2022/11/aws-lambda-support-node-js-18/)
- yarn v3
  - [yarn v3 の独自機能を避けつつ yarn v1 から v3 へのアップグレードをする](https://zenn.dev/mizchi/articles/yarn-v1-to-v3)
  - [yarn3 が出たことだし pnp 使ってみる](http://var.blog.jp/archives/85307370.html)