Serverless Framework と Lambda + API Gateway でサーバーレスな動的サイトを構築する方法を紹介します。
いろいろと試行錯誤が必要でしたが、できあがってみれば意外と簡単でした。
あと、この方法ではローカルでも動作確認ができるのでサクサクと開発できると思います。
セットアップ
なにはともあれ npm init
。
その後、以下のモジュールをインストールしてください。
$ npm install serverless serverless-offline --save-dev
serverless-offline
というモジュールは Serverless Framework のプラグインで、これを使用するとローカルでアプリを実行することができます。
あと、package.json
の scripts
に、以下のような感じの項目も追加。
"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.json
に npm 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
サンプル
今回紹介したサンプルのリポジトリは以下です。