はじめに
フロントエンド開発のためにAPIのモックが必要になったので、json-serverを利用してモックサーバを構築していきます。
基本的な環境構築
初期化
# プロジェクトディレクトリを作成し, 移動する
mkdir mock-api
cd ./mock-api
# 初期化処理
npm init -y
json-server
今回のメインとなる json-server を導入します。
npm i -D json-server
contents.json
エンドポイントとなる json ファイルを作成します。
mkdir api
new-item api/contents.json
作成した contents.json を編集します。
ここで編集した内容がAPIのレスポンスとして返されるようになります。
{
"contents": [
{
"id": 1,
"title": "title - foo",
"body": "body - bar",
"author-id": 1
},
{
"id": 2,
"title": "title - foo2",
"body": "body - bar",
"author-id": 1
},
{
"id": 3,
"title": "title - bar",
"body": "body - bal",
"author-id": 2
}
]
}
package.json
package.json を更新します。
{
"name": "mock-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
### ↓↓↓↓↓ ここから追加 ↓↓↓↓↓ ###
"json-server": "json-server --watch ./api/contents.json --port 5000"
### ↑↑↑↑↑ ここまで追加 ↑↑↑↑↑ ###
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"json-server": "^0.16.1"
}
}
実行
npm run
コマンドで実行します。
npm run json-server
実行されると、以下にGET通信することで先ほどのcontents.jsonの内容が得られます。
http://localhost:5000/contents
応用的な環境構築
エンドポイントを複数用意したい場合
エンドポイントを複数用意したい場合、contents.jsonにもう一つ要素を追加することで解決します。
{
"contents": [
{
"id": 1,
"title": "title - foo",
"body": "body - bar",
"author-id": 1
},
{
"id": 2,
"title": "title - foo2",
"body": "body - bar",
"author-id": 1
},
{
"id": 3,
"title": "title - bar",
"body": "body - bal",
"author-id": 2
}
],
"authors": [
{
"id": 1,
"name": "hoge"
},
{
"id": 2,
"name": "fuga"
}
]
}
上記のように編集し実行すると、以下のように通信先を切り替えることができます。
http://localhost:5000/contents
http://localhost:5000/authors
エンドポイント毎にファイルを分割したい場合
しかし、APIの規模が大きくなってくると単一ファイルではメンテナンスが難しくなってくることは想像に難しくありません。
そうなると「エンドポイント毎にファイルを分割したい」という欲求が生まれてきます。
そこで問題となってくるのが json-server の「単一ファイルしか受け付けない」という仕様です。
なので、今回は複数ファイルを一つにマージすることで対応したいと思います。
【参考】
- Json-serverでモックAPI
(1) まず、マージをするためのスクリプトを用意します
mkdir scripts
new-item merge.js
const path = require("path");
const fs = require("fs");
const root = path.resolve("./", "api");
const update = () =>
{
const api = fs.readdirSync(root).reduce((api, file) => {
if (api === undefined)
api = {};
if (path.extname(file) == ".json") {
const endpoint = path.basename(file, path.extname(file));
if (api[endpoint] === undefined)
api[endpoint] = {};
api[endpoint] = JSON.parse(fs.readFileSync(root + "/" + file, "utf-8"));
return api;
}
}, {});
fs.writeFile(root + "/../merged.json", JSON.stringify(api), err => {
if (err)
throw err;
});
}
// 初回作成
update();
// jsonファイルを監視し, 監視ファイルに更新があるたびmerged.jsonを更新
fs.watch(root, (e, filename) => update());
(2) json-server と merge.js を両方同時に動作させるために npm-run-all を導入します
npm i -D npm-run-all
(3) package.json を更新します
{
"name": "mock-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
### ↓↓↓↓↓ ここから追加・更新 ↓↓↓↓↓ ###
"json-server": "json-server --watch merged.json --port 5000",
"merge": "node ./scripts/merge.js",
"serve": "npm-run-all -p merge json-server"
### ↑↑↑↑↑ ここまで追加・更新 ↑↑↑↑↑ ###
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"json-server": "^0.16.1"
}
}
(4) contents.json を contents.json と authors.json に分割します
new-item api/authors.json
{
"contents": [
{
"id": 1,
"title": "title - foo",
"body": "body - bar",
"author-id": 1
},
{
"id": 2,
"title": "title - foo2",
"body": "body - bar",
"author-id": 1
},
{
"id": 3,
"title": "title - bar",
"body": "body - bal",
"author-id": 2
}
]
}
{
"authors": [
{
"id": 1,
"name": "hoge"
},
{
"id": 2,
"name": "fuga"
}
]
}
(5) 以下のコマンドで実行します
npm run serve
これで複数ファイルに分割定義することが可能となります。
POSTやPUTでもレスポンスを受け取りたい場合
json-server は GET以外 のリクエストだと思ったようにレスポンスを返してくれないので、処理をフックして GET通信 に偽装します。
【参考】
- json-server で使い捨てモックサーバを作る
- JSON Serverを使ってGETとPOSTでレスポンスを変えてみた
(1) まず、処理をフックするためのスクリプトを追加します
new-item ./scripts/middleware.js
module.exports = (req, res, next) =>
{
if(req.method == 'POST') {
req.method = 'GET' // GETに偽装
req.query = req.body
}
next()
}
(2) package.json を更新します
以下では、--middlewares オプションを追加しています。
{
"name": "mock-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
### ↓↓↓↓↓ ここから更新 ↓↓↓↓↓ ###
"json-server": "json-server --watch merged.json --port 5000 --middlewares ./scripts/middleware.js",
### ↑↑↑↑↑ ここまで更新 ↑↑↑↑↑ ###
"merge": "node ./scripts/merge.js",
"serve": "npm-run-all -p merge json-server"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"json-server": "^0.16.1"
}
}
これでPOST通信でもjsonレスポンスを得ることができます。
APIのrouteをカスタムしたい場合
現状、APIのrouteが http://localhost:5000/{jsonファイル名} となっているため、これを http://localhost:5000/api/v1/{jsonファイル名} となるように変更してみたいと思います。
【参考】
- Json-serverでモックAPI
(1) まず、routes.json を追加します
new-item ./routes.json
{
"/api/v1/*": "/$1"
}
(2) package.json を更新します
以下では、--routes オプションを追加しています。
{
"name": "mock-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
### ↓↓↓↓↓ ここから更新 ↓↓↓↓↓ ###
"json-server": "json-server --watch merged.json --port 5000 --routes ./routes.json --middlewares ./scripts/middleware.js",
### ↑↑↑↑↑ ここまで更新 ↑↑↑↑↑ ###
"merge": "node ./scripts/merge.js",
"serve": "npm-run-all -p merge json-server"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"json-server": "^0.16.1"
}
}
これで**http://localhost:5000/api/v1/{jsonファイル名}**でアクセスできるようになります。
おわりに
さらに詳しくは 公式サイト をご参照ください。