LoginSignup
3
7

More than 5 years have passed since last update.

Single Page Application を Serverless Framework と React でやる Tutorial(4)

Posted at

前回までで 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 で作成したコードを紹介します。

3
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
7