はじめに
フロントエンド開発のためにAPIのモックが必要になったので、json-serverを利用してモックサーバを構築していきます。
基本的な環境構築
初期化
# プロジェクトディレクトリを作成し, 移動するmkdirmock-apicd./mock-api# 初期化処理npminit-y
json-server
今回のメインとなる json-serverを導入します。
npmi-Djson-server
contents.json
エンドポイントとなる json ファイルを作成します。
mkdirapinew-itemapi/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
コマンドで実行します。
npmrunjson-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) まず、マージをするためのスクリプトを用意します
mkdirscriptsnew-itemmerge.js
constpath=require("path");constfs=require("fs");constroot=path.resolve("./","api");console.log(`root= ${root}`);constupdate=()=>{constapi=fs.readdirSync(root).reduce((api,file)=>{if(api===undefined)api={};if(path.extname(file)==".json"){constendpoint=path.basename(file,path.extname(file));if(api[endpoint]===undefined)api[endpoint]={};api[endpoint]=JSON.parse(fs.readFileSync(root+"/"+file,"utf-8"));returnapi;}},{});fs.writeFile(root+"/../merged.json",JSON.stringify(api),err=>{if(err)throwerr;});}// 初回作成update();// jsonファイルを監視し, 監視ファイルに更新があるたびmerged.jsonを更新fs.watch(root,(e,filename)=>update());
(2) json-serverと merge.jsを両方同時に動作させるために npm-run-allを導入します
npmi-Dnpm-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-itemapi/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) 以下のコマンドで実行します
npmrunserve
これで複数ファイルに分割定義することが可能となります。
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ファイル名}でアクセスできるようになります。
おわりに
さらに詳しくは 公式サイトをご参照ください。