前回までで local で WEB API を開発するやり方がぼんやりと見えてきたと思います。
今回は S3 に React を配備して SPA を Serverless Framework で使用する場合の開発環境を考えます。
React の雛形と、 Serverless Framework の雛形をそれぞれ作成します。
mkdir serverless-tutorial-four && cd $_
create-react-app front
sls create --template aws-nodejs --path server
とりあえず GET http://localhost:3000/
に対して 現在時刻
を返す API を作っておきます。
cd server
yarn init -y
yarn add moment express serverless-http --save
yarn add serverless-offline serverless-finch --dev
serverless.yml
を修正します。custome.client.bucketName
に関しては各自で S3 のバケットを生成してください。
service: server
plugins:
- serverless-finch
- serverless-offline
custom:
client:
bucketName: [your-bucket-name]
distributionFolder: ../front/build
provider:
name: aws
runtime: nodejs6.10
stage: dev
region: ap-northeast-1
functions:
app:
handler: handler.main
events:
- http:
method: ANY
path: '/'
cors: true
- http:
method: ANY
path: '{proxy+}'
cors: true
handler.js を修正します。
const serverless = require('serverless-http');
const express = require('express');
const moment = require('moment');
const app = express();
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*")
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS")
next()
});
app.get('/api/now', function (req, res) {
res.json({ now: moment().format('YYYY-MM-DD HH:mm:ss') });
});
module.exports.main = serverless(app);
sls offline --port 4000
を実行した後下記コマンドを実行します。
% curl "http://localhost:4000/api/now"
{"now":"2018-04-06 21:21:31"}
本題
以下を実行します。先ほど serverless の port を 4000 に指定していると以下のコマンドでは port 3000 で React の開発サーバーが起動します。
cd front
yarn add axios --save
yarn start
ということで package.json
に以下を追記します。
"proxy": {
"/api": {
"target": "http://localhost:4000"
}
}
この proxy は react-scripts@0.2.3
より Development モードで動作するようになっています。
実装
front/src/App.js
を修正します。
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import axios from 'axios'
const BASE_URL = '/';
class App extends Component {
constructor(props) {
super(props)
this.state = { now: "" }
}
componentWillMount() {
axios.get(`${BASE_URL}/api/now`).then((res) => {
console.log(res);
this.setState({now: res.data.now});
})
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<h2>Now: {this.state.now}</h2>
</div>
);
}
}
export default App;
http://localhost:3000/ を開いて動作確認をして下さい。
デプロイする
- Function と Endpoint をデプロイ
- S3 をデプロイ
Function と Endpoint をデプロイ
おもむろに以下のコマンドを実行します。
% sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (6.95 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
.................................
Serverless: Stack update finished...
Service Information
service: server
stage: dev
region: ap-northeast-1
stack: server-dev
api keys:
None
endpoints:
ANY - https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/
ANY - https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/{proxy+}
functions:
app: server-dev-app
curl https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/api/now
を実行すると現在時刻が返ってくると思います。
というわけで React App を build するときにこの長い URL を伝える方法を考えないといけないわけです。
process.env.REACT_APP_GW_URL
serverless-plugin-build-create-react-app のような方法もあるようですが、ここではシンプルに以下のようにしました。
src/App.js
の BASE_URL の定義を下記のようにします。
// const BASE_URL = '';
const BASE_URL = process.env.REACT_APP_GW_URL ? process.env.REACT_APP_GW_URL : '';
その後 serverless deploy した時に表示された API Gateway の URL を設定します。
export REACT_APP_GW_URL="https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev"
yarn build
これで front/build/
配下に API Gateway にアクセスする React App が生成されます。
これを S3 にアップロードしましょう。
serverless-finch
serverless-s3-deploy が Deprecated になっているのでこちらを使用します。
適当な Bucket を作成してください。Bucket を作成する方法はここでは割愛します。
server のディレクトリへ移動してから serverless client deploy
を実行すると
表示された Bucket の URL を開くとローカルで作成した React App が動作していると思います。
まとめ
今回は S3 + API Gateway + Lambda の example を作成しました。 dynamoDB に関しては含めて説明をしませんでしたが前回の Tutorial で説明済みのため割愛しました。
次回は総集編として以前作成した React tutorial で作った fav-articles を Serverless Framework で作成したコードを紹介します。