Posted at

Serverless framework と Lambda + API Gateway でサーバーレスな動的サイトをつくる

Serverless Framework と Lambda + API Gateway でサーバーレスな動的サイトを構築する方法を紹介します。

いろいろと試行錯誤が必要でしたが、できあがってみれば意外と簡単でした。

あと、この方法ではローカルでも動作確認ができるのでサクサクと開発できると思います。


セットアップ

なにはともあれ npm init

その後、以下のモジュールをインストールしてください。

$ npm install serverless serverless-offline --save-dev

serverless-offline というモジュールは Serverless Framework のプラグインで、これを使用するとローカルでアプリを実行することができます。

あと、package.jsonscripts に、以下のような感じの項目も追加。

  "scripts": {

"start": "sls offline start",
"deploy": "sls deploy --stage dev",
"deploy:prod": "sls deploy --stage prod",
"test": "echo \"Error: no test specified\" && exit 1"
},

テストはお好みでどうぞ。


Serverless Framework の設定

必要最小限な構成は以下の通り。意外と簡単!

service: serverless-cms

frameworkVersion: ">=1.29.2 <2.0.0"

plugins:
- serverless-offline

provider:
name: aws
runtime: nodejs8.10
memorySize: 512
region: ap-northeast-1

functions:
api:
handler: handler.app
events:
- http:
path: /
method: get
- http:
path: /{any+}
method: get

この例では、Lambda Proxy を使っていて、すべての URL に対するリクエストを handler.app でキャッチしています。

あとは、handler.app でレスポンスヘッダーやコンテンツをゴニョゴニョする感じです。


ラムダ関数の例

以下のソースを handler.js というファイル名で保存してください。

'use strict';

module.exports.app = (event, context, callback) => {
callback(null, {
statusCode: 200,
body: `<html><head><title>Hello World</title></head><body>
<h1>Hello World!</h1>
<pre>${JSON.stringify(event, null, 2)}</pre>
</body></html>`,
headers: {
"Content-Type": "text/html"
}
}
);
}

callback() の第二引数に渡している連想配列で、ブラウザで表示するためのコンテンツを定義しています。

スタータスコードとHTMLコンテンツ、あとレスポンスヘッダーを指定できるので、必要なことはなんでもできそうですね。

この例では、どんな URL にアクセスがあっても 200 を返していますが、実用的なウェブアプリにするには、event.path で判別してレスポンスヘッダーを適切にコントロールする必要があります。


ローカル環境での動作確認

上で、package.jsonnpm start 用のコマンドを追加していればそれを叩くだけです。

$ npm start

ローカルでの開発環境が手軽に立ち上がるのはかなりうれしいですね。


AWS へのデプロイ

以下のような感じで、AWS のクレデンシャルを環境変数として設定。

$ export AWS_ACCESS_KEY_ID=xxxx

$ export AWS_SECRET_ACCESS_KEY=xxxx

僕はプロジェクトディレクトリごとに direnv で設定する方法がお気に入りです。

以上が終わったらデプロイ用のコマンドを実行しましょう。

$ npm run deploy

コマンド出力の最後に以下のような出力があるので、その URL にアクセスすればオッケーです。

Service Information

service: serverless-cms
stage: dev
region: ap-northeast-1
stack: serverless-cms-dev
api keys:
None
endpoints:
GET - https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/
GET - https://xxxx.execute-api.ap-northeast-1.amazonaws.com/dev/{any+}
functions:
api: serverless-cms-dev-api
layers:
None

上で紹介した package.json の記述例ではステージングと本番を切り替えてデプロイすることも想定しています。

本番にデプロイするには、以下のような感じです。

$ npm run deploy:prod


サンプル

今回紹介したサンプルのリポジトリは以下です。

https://github.com/miya0001/serverless-webapp