Serverless FrameworkでTypeScriptのサーバーレスAPIをAWSにデプロイしてみた

![](https://day-journal.com/memo/images/try-056_01.gif)

<br>

![](https://day-journal.com/memo/images/logo/serverless-framework.png)

<br>

この記事は、「[AWS Advent Calendar 2020](https://qiita.com/advent-calendar/2020/aws)」の20日目の記事です。

### Serverless FrameworkでTypeScriptのサーバーレスAPIをAWSにデプロイしてみました :tada:  

<br>

事前準備

- Serverless Frameworkの環境構築
[環境構築](https://day-journal.com/memo/serverless-framework-001)

- AWSの設定
[AWS事前準備](https://day-journal.com/memo/serverless-framework-002)

<br>

事前設定ができていれば**3コマンド**でデプロイできます！  

<br>

はじめに、TypeScriptテンプレートでプロジェクトを作成します。

```shell
sls create -t aws-nodejs-typescript -p sample
```

![画像](https://day-journal.com/memo/images/try-056_02.png)

<br>

次に、対象プロジェクトに移動しパッケージをインストールします。

```shell
cd sample
npm install
```

![画像](https://day-journal.com/memo/images/try-056_03.png)

<br>

作成されたプロジェクトを確認します。今回は、「serverless.ts」のみ変更します。

#### package.json

```json
{
  "name": "sample",
  "version": "1.0.0",
  "description": "Serverless webpack example using Typescript",
  "main": "handler.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "source-map-support": "^0.5.19"
  },
  "devDependencies": {
    "@serverless/typescript": "^2.12.0",
    "@types/aws-lambda": "^8.10.64",
    "@types/node": "^14.14.6",
    "fork-ts-checker-webpack-plugin": "^6.0.0",
    "serverless-webpack": "^5.2.0",
    "ts-loader": "^8.0.10",
    "ts-node": "^9.0.0",
    "typescript": "^4.0.5",
    "webpack": "^5.4.0",
    "webpack-node-externals": "^2.5.2"
  },
  "author": "The serverless webpack authors (https://github.com/elastic-coders/serverless-webpack)",
  "license": "MIT"
}
```

<br>

#### tsconfig.json

```json
{
  "compilerOptions": {
    "lib": ["es2017"],
    "removeComments": true,
    "moduleResolution": "node",
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "sourceMap": true,
    "target": "es2017",
    "outDir": "lib"
  },
  "include": ["./**/*.ts"],
  "exclude": [
    "node_modules/**/*",
    ".serverless/**/*",
    ".webpack/**/*",
    "_warmup/**/*",
    ".vscode/**/*"
  ]
}
```

<br>

#### webpack.config.js

```javascript
const path = require('path');
const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

module.exports = {
  context: __dirname,
  mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
  entry: slsw.lib.entries,
  devtool: slsw.lib.webpack.isLocal ? 'eval-cheap-module-source-map' : 'source-map',
  resolve: {
    extensions: ['.mjs', '.json', '.ts'],
    symlinks: false,
    cacheWithContext: false,
  },
  output: {
    libraryTarget: 'commonjs',
    path: path.join(__dirname, '.webpack'),
    filename: '[name].js',
  },
  optimization: {
    concatenateModules: false,
  },
  target: 'node',
  externals: [nodeExternals()],
  module: {
    rules: [
      // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
      {
        test: /\.(tsx?)$/,
        loader: 'ts-loader',
        exclude: [
          [
            path.resolve(__dirname, 'node_modules'),
            path.resolve(__dirname, '.serverless'),
            path.resolve(__dirname, '.webpack'),
          ],
        ],
        options: {
          transpileOnly: true,
          experimentalWatchApi: true,
        },
      },
    ],
  },
  plugins: [
    // new ForkTsCheckerWebpackPlugin({
    //   eslint: true,
    //   eslintOptions: {
    //     cache: true
    //   }
    // })
  ],
};
```

<br>

#### handler.ts

```typescript
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),
  };
}
```

<br>

#### serverless.ts

```typescript
import type { AWS } from '@serverless/typescript';

const serverlessConfiguration: AWS = {
  service: 'sample',
  frameworkVersion: '2',
  custom: {
    webpack: {
      webpackConfig: './webpack.config.js',
      includeModules: true
    }
  },
  // Add the serverless-webpack plugin
  plugins: ['serverless-webpack'],
  provider: {
    name: 'aws',
    runtime: 'nodejs12.x',
    region: 'ap-northeast-1',
    profile: 'AWSのプロファイルユーザー名',
    apiGateway: {
      minimumCompressionSize: 1024,
    },
    environment: {
      AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1',
    },
  },
  functions: {
    hello: {
      handler: 'handler.hello',
      events: [
        {
          http: {
            method: 'get',
            path: 'hello',
          }
        }
      ]
    }
  }
}

module.exports = serverlessConfiguration;
```

対象のリージョンを設定します。

```typescript
region: 'ap-northeast-1',
```

対象のAWSのプロファイルユーザー名を設定します。

```typescript
profile: 'AWSのプロファイルユーザー名',
```

<br>

プロジェクトが完成したらAWSにデプロイします。

```shell
sls deploy
```

![画像](https://day-journal.com/memo/images/try-056_04.png)

<br>

デプロイ後に、AWSのコンソールでLambdaが作成されているのを確認してみます。

![画像](https://day-journal.com/memo/images/try-056_05.png)

<br>

表示されました :tada:  

![画像](https://day-journal.com/memo/images/try-056_06.png)

<br>

#### Serverless FrameworkでTypeScriptのサーバーレスAPIをAWSにデプロイできました :thumbsup: 

Serverless Frameworkを利用することで、手軽にAWSにサーバーレス環境をデプロイできました :bulb: 色々と設定できそうなので今後も試していきたいと思います :grinning: 

最近、設定ファイルが「**serverless.ts**」もサポートされたようです :muscle: 

以前にZappaでためした記事、「[ZappaでDBもパッケージしたサーバーレスAPIを構築してみた](https://day-journal.com/memo/try-015)」もあるので比較してみて頂ければと思います。 

<br>

Serverless Frameworkについて、他にも記事を書いています。よろしければぜひ :bow:
<a href="https://day-journal.com/memo/tags/Serverless-Framework"" target="_blank">tags - Serverless Framework</a>

やってみたシリーズ :grinning:
<a href="https://day-journal.com/memo/tags/Try" target="_blank">tags - Try</a>

<br>
<br>

<a href="https://dayjournal.booth.pm" target="_blank"><img src="https://day-journal.com/memo/images/etc/book.png" alt="book"></a>