Serverless Components はオレたちの未来を劇的にスケールさせるか

![](https://camo.githubusercontent.com/db47fe1b099d427f1b040294fbe0f7102ca4a7ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f7075626c69632e6173736574732e7365727665726c6573732e636f6d2f696d616765732f726561646d655f7365727665726c6573735f636f6d706f6e656e74732e676966)

Serverless.inc 社より、[Serverless Components](https://github.com/serverless/components) がついに GA されました。

近年のアプリケーション開発では、いくつかの SaaS を組み合わせることで超高速に開発を行うことができます。例えば「認証は Auth0、ホスティングは Netlify、バックエンド API は AWS Lambda を使用する」といった具合です。このように複数のサービスを組み合わせることで、Undifferentiated Heavy Lifting な作業を排除できます。開発者は価値を生み出すビジネスロジックにのみ集中できるようになるのです。

以下はサーバレスアーキテクチャの例です。複数の SaaS を組み合わせて構築しています。

![architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163591/af1ad149-c9d4-7310-d57a-f0255e638433.png)

SaaS を組み合わせるだけで、一定の機能群を作り上げることができる時代になりました。しかし、それにしても複雑な管理は残ります。アプリケーション開発者は複数のサービスを手作業で組み合わせなければならず、構築と構成管理に一定の複雑度を残してしまいます。

そこで、Serverless Components です。

Serverless Components は、全てのクラウドベンダー、 SaaS ベンダーに対してインフラとアプリをプロビジョニングします。すでに提供されているコンポーネントを組み合わせるだけで即座にアプリケーションを構築できます。

従来 Serverless Framework は function と event は簡単に定義できていましたが、インフラリソースをプロビジョニングするためにはどうしても Cloudformation を定義する必要がありました。
また、プロビジョニングできる対象も AWS や GCP などの特定のクラウドベンダーのサービスにしか対応しておらず、Auth0 などを使用する場合は自前で構成管理をする必要がありました。Serverless Components なら様々な SaaS に対応できます。

# コンポーネント

Serverless Component は React のコンポーネントと同じ構造に基づいています。個々のコンポーネントを参照したり、複数のコンポーネントを同時に作成できます。

先の例をコンポーネントを使用して構築すると以下のように分解ができます。もちろん、より小さくコンポーネントを分割することもできます。ここでは最小の意味のある単位で分割した場合を図示しています。

![components.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163591/3e26b1c1-fffc-1dba-60e4-b1d57bd83113.png)

サーバレスコンポーネントは、高次のユースケース（ウェブサイト、ブログ、請求システムなど）を中心に構築されています。関係のない低レベルなインフラの詳細は抽象化され、代わりに単純な構成が提供されます。例えば、S3 の静的サイト公開設定や、ログ記録、暗号化設定などはユースケースに対しては意識する必要はありません。事前に設定済みのコンポーネントを使用すれば良いのです。

これはソフトウェア開発における基本的な考え方 **関心の分離 (Separation of Concerns: SoC)** に基づいていますね。確かに Infrastructure as Code をやっていると、インフラリソースの細部まで理解して構築する必要があり、多大な学習コストを要していました。

# ServerlessComponents を使用したウェブサイト

さて、まずは最もシンプルなアプリケーションを Serverless Component を使用して構築してみましょう。
ここでは、GitHub のリポジトリでも例としてあげている **サーバレスウェブサイト** を構築することにします。

今回構築するウェブサイトは、AWS S3 でホストされます。無料の AWS ACM SSL 証明書で保護された AWS Route 53 のカスタムドメインでアクセスします。さらに、静的コンテンツは、AWS Cloudfront を使用して迅速かつグローバルに配信されます。

![website.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163591/c490b20d-a81b-b96d-9af9-3841ea07437c.png)

従来このような構成を実現する場合、ServerlessFramework に直接 Cloudformation を書き下し、各リソース間の詳細な設定と依存関係を意識する必要がありました。数百行の Cloudformation のテンプレートが必要でしょう。

Serverless Components を使用する場合はこれだけです。

```yaml
component: website
name: website
inputs:
  src:
    src: ./src
    hook: npm run build
    dist: ./dist
  domain: geeawa.ga
```

驚異的なほど、シンプルです。
`component: website` として、website コンポーネントを使用することを宣言し、そのコンポーネントに渡す設定値を `input:` にて指定しています。ただ、それだけです。

## Serverless Components を使用してウェブサイトを構築する

実際に website コンポーネントを使用してこの構成を作ってみましょう。

### Install

まずは最新バージョンの Serverless Framework をインストールします。

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

### Create

サンプルとして、以下のようにテンプレート URL を指定して構築します。

```
$ serverless create --template-url https://github.com/serverless/components/tree/master/templates/website
$ cd website
```

次に、`.env` ファイルを使用して AWS アクセスキーの情報を記載しましょう。`.env`ファイルは `website` のルートディレクトリに作成します。

```
AWS_ACCESS_KEY_ID=XXX
AWS_SECRET_ACCESS_KEY=XXX
```

ディレクトリ構成は以下のようになっているはずです。

```
|- src
  |- index.html
|- serverless.yml
|- .env
```

### Deploy

あとはデプロイをするだけです。

```bash
$ serverless deploy
```

デプロイが完了すると以下のようにウェブサイトの URL が発行されます。Cloudfront へ配信が完全に完了するまでに少し時間がかかることに注意してください。

```bash
serverless ⚡ framework
Action: "deploy" - Stage: "dev" - App: "landing-page" - Instance: "landing-page"

bucket:    website-089y5jm
bucketUrl: http://website-089y5jm.s3-website-us-east-1.amazonaws.com
url:       https://d2u9prrumf2g64.cloudfront.net
domain:    https://www.geeawa.ga
```

以下のようなサイトがデプロイされています。

![page.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163591/9ddb1095-0365-f1c0-037d-fe3abe760a22.png)

### Dev Mode

さらに興味深い機能として Dev Mode があります。開発中にソースディレクトリの変更を監視し、保存すると即座にデプロイできます。

![sls.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163591/6fd210ff-6cd3-90ae-e020-2686c1ac3485.gif)

### Remove

作成されたインフラを破棄する場合は、serverless.yml ファイルが含まれているディレクトリで次のコマンドを実行するだけです。

```
$ serverless remove
```

# コンポーネントを自作する

コンポーネントを自作するためには以下の２つのファイルが必要です。

- serverless.component.yml: ServerlessComponent の定義を記入します。
- serverelss.js: ServerlessComponent のコード（実装）を記述します。

### serverless.component.yml

コンポーネントをサーバーレスレジストリ内で利用できるようにするためには `serverless.component.yml` を作成する必要があります。

```yaml
# serverless.component.yml

name: express # 必須 コンポーネント名
version: 0.0.4 # 必須 バージョン
author: eahefnawy # 必須 著者
org: serverlessinc # 必須 開発組織名
description: Deploys Serverless Express.js Apps # 任意 説明
keywords: aws, serverless, express # 任意 registry.serverless.comで検索するときに引っかかるキーワード
repo: https://github.com/owner/project # 任意 ソースコードのリポジトリURL
license: MIT # 任意 ライセンス
main: ./src # 任意 コンポーネントのソースコードが格納されているディレクトリ
```

### serverless.js

`serverless.js`には以下のように実装していきます。React の思想にインスパイアされており、`Component` を継承したつくりになっています。`deploy`, `remove`などの Function を書いていくことになります。

```js
// serverless.js

const { Component } = require("@serverless/core");

class MyBlog extends Component {
  async deploy(inputs) {
    console.log("Deploying a serverless blog"); // --debug モードで実行するとログが出力されます。
    this.state.url = outputs.url; // stateに保存する
    return outputs;
  }
}

module.exports = MyBlog;
```

`deploy()` は必ず書く必要があります。`deploy()` は、コンポーネントが何らかのクラウドリソースを作成するためのロジックが存在する場所です。`serverless deploy` コマンドを実行すると、常に `deploy()` メソッドが呼び出されます。

このクラスに他のメソッドを追加することもできます。`remove()` ではサーバレスコンポーネントが作成したクラウドリソースを全て削除します。

他にもメソッドはいくつでも追加できます。コンポーネントを追加機能付きでプロビジョニングしたい場合などに拡張できる作りになっています。

Serverless Components は `test()`, `logs()`, `metrics()` 機能を備えたコンポーネント、またはデータベースコンポーネントの初期値を確立するためのコンポーネント `seed()` の開発に着手しているようです。

メソッド以外の `deploy()` メソッドはすべてオプションです。すべてのメソッドは、`inputs` 個別の引数ではなく単一のオブジェクトを取り、単一のオブジェクト `outputs` を返します。

# まとめ

クラウドや SaaS ベンダーのリソースを統一的に管理し、再利用可能にするプラットフォームが Serverless Components です。

[現在公式が提供しているコンポーネント](https://github.com/serverless-components)は 67 種類(2020/04/06 現在)です。
まずは AWS や Kubernates 関連がラインナップし始めています。急激に拡大しています。もう **本当に必要なものだけを実装し、組み合わせるだけ** という開発スタイルに変わりはじめています。

これこそがクラウドテクノロジーの目指していたところかもしれません。さらなる発展が楽しみですね。