Node.js
Express
reactjs
create-react-app

React.jsアプリケーションとREST APIのスタブをローカルで同時に起動する

背景

React.js(create-react-app)を元に
REST APIとのつなぎ込みが必要なフロントエンドの開発をしていると、
APIの返す値が異なる条件での動きを手元で検証したいときがある。

View側にモックを埋め込むのは微妙なので、APIのスタブが欲しい。

サーバ側にログインするのは面倒なので、開発機にAPIサーバを立て、
ローカルのjsonを編集するとレスポンスも変わるようにしたい。

概要

  • Expressを使ったREST APIのBoilerplateを改変し、ローカルのjsonファイルを参照させる
  • フロント側のpackage.jsonで、Reactのアプリケーションとスタブを同時起動させる

スタブのセットアップ

https://github.com/developit/express-es6-rest-api

を利用

ソースの取得

# githubからclone
git clone git@github.com:developit/express-es6-rest-api.git
# ディレクトリ名をstubに変更
mv express-es6-rest-api stub
# package.json生成
cd stub
rm -rf .git && npm init

DB依存箇所の削除

今回はローカルのjsonを返すので、DBに関わるファイルを削除。

rm src/db.js
rm src/api/facets.js
rm -r src/lib/
rm -r src/models/

DB依存箇所を書き換え

ファイル依存するように書き換えていく

src/index.js

import http from 'http'
import express from 'express'
import cors from 'cors'
import morgan from 'morgan'
import bodyParser from 'body-parser'
import middleware from './middleware'
import api from './api'
import config from './config.json'

let app = express()
app.server = http.createServer(app)

// logger
app.use(morgan('dev'))

// 3rd party middleware
app.use(cors({
  exposedHeaders: config.corsHeaders
}))

app.use(bodyParser.json({
  limit: config.bodyLimit
}))

// internal middleware
app.use(middleware({ config }))

// api router
app.use('/stub/api', api({ config }))

app.server.listen(process.env.PORT || config.port)

console.log(`Started on port ${app.server.address().port}`)

export default app

src/middleware/index.js

import { Router } from 'express'

export default () => {
  let routes = Router()

  // add middleware here

  return routes
}

src/api/index.js

import { version } from '../../package.json'
import { Router } from 'express'
import fs from 'fs'

const readJson = (path) => {
  // パスは stub/ からの相対パス
  return JSON.parse(fs.readFileSync(path, 'utf8'))
}

export default ({ config }) => {
    let api = Router()

    api.get('/users/me', (req, res) => {
        res.json(readJson('./src/api/users/GET/me.json'))
    })
    api.get('/users/:id', (req, res) => {
        res.json(readJson('./src/api/users/GET/id.json'))
    })

    return api;
}

apiのディレクトリに以下のファイルを設置

  • src/api/users/GET/me.json
  • src/api/users/GET/id.json

APIを起動し、疎通確認

# API起動
npm run start
# 動作確認 (先程設置したjsonが返ってくる)
curl -X GET 'http://localhost:8080/stub/api/users/me'
curl -X GET 'http://localhost:8080/stub/api/users/2'

フロント側の修正

React.jsアプリケーションとスタブを同時起動する設定

  • package.json の devDependencies に npm-run-all を追加 (複数タスクの並列実行に必要)
  • package.json の scripts に以下の3行を追加
    "local": "run-p local:*",
    "local:start": "react-scripts start",
    "local:stub": "cd ./stub; npm run start",

これを設定すると、 以後は npm run local
フロントとスタブが同時に起動するようになる。

stubの生成物をgitにcommitしないようにする

フロント側の .gitignore に 以下を追記

# stub
stub/dist