json-server x vercel で最速無料モックAPIサーバ構築
json-serverで作ったモックAPIサーバを公開ネットワークからでも使えるように、vercelにデプロイする。
微妙にいろいろハマったのでメモしておく。
JSON Serverを使ってAPIサーバ実装
npm --init
でプロジェクト初期化。
npm i json-server@0.7.14
で json-server インストール。
json-server は v1 がまだベータ版だし、ちょっとインターフェースが変わっている感じなので、安定している v0.7.14 を使っておく。
db.json として レスポンスデータファイルを作成、プロジェクトルートに配置。
※ api/category1/resource1
のようなエンドポイントの場合、JSON上 category1 > resource1 のような階層構造で定義するとうまくいかなかったので、 category1_resource1
のようなキーで定義しておいてルーティング定義で書き換えることにする(違う方法もあるかも)
{
"category1_resource1": {
"foo1":"bar1"
},
"category1_resource2": {
"foo2":"bar2"
}
"category2_resource1": {
"foo3":"bar3"
}
}
必要に応じてルーティング書き換えのための routes.json を作成、プロジェクトルートに配置。
ここでは、前述の事情のため、エンドポイントの階層を _
に書き換える。
{
"/api/*/*": "/$1_$2",
}
package.json の script に以下を定義
"scripts": {
"start": "json-server -p 3000 --watch db.json --routes routes.json"
}
npm run start
で実行。
ブラウザから http://localhost:3000/api/category1/resource1 にアクセスしてみてレスポンスが表示されれば成功。
JSON Serverをvercelで動くようにする準備
vercelのアカウントがなければ作成しておく。
githubに公開リポジトリを作成(privateでもいけるんだったかも)。
api/server.js
を作成し、以下のように定義する。
細かいハマりポイントがいろいろあった。
- server.js は api 配下に置いておかないと、今のvercelだとうまくいかないっぽかった
- db.json を参照するときに、
fs.readFileSync('db.json', 'utf-8');
だと参照できない-
公式を見ると
path.join(process.cwd(), 'db.json')
のようにしろと書いているんだけど、これだとダメだった - 結局
path.resolve(__dirname, '..', 'db.json')
なら参照できたのでこれでいく
-
公式を見ると
- POSTでリソースを更新する必要がないなら、単に
jsonServer.router(filePath)
でもよさそう
const jsonServer = require('json-server');
const server = jsonServer.create();
const fs = require('fs');
const path = require('path');
const filePath = path.resolve(__dirname, '..', 'db.json');
const data = fs.readFileSync(filePath, "utf-8");
const db = JSON.parse(data);
const router = jsonServer.router(db);
const middlewares = jsonServer.defaults();
server.use(middlewares);
server.use(
jsonServer.rewriter({
"/api/*/*": "/$1_$2",
})
);
server.use(router);
server.listen(3000, () => {
console.log("listening on port: 3000");
});
module.exports = server;
プロジェクトルートに vercel.json を作成。
古いサンプルだと rewrites
の代わりに routes
が使われていたり、functions
の代わりに builds
が使われていたりする。
現行バージョンだと rewrites
, functions
を使うのが正しいっぽい。
参考)https://vercel.com/docs/projects/project-configuration
{
"functions": {
"api/server.js": {
"memory": 1024,
"includeFiles": "db.json"
}
},
"rewrites": [
{
"source": "/(.*)",
"destination": "api/server.js"
}
]
}
package.json の script を以下のように変更し、ローカルでも動くことを確認しておく。
"scripts": {
"start-node": "node api/server.js"
}
vercelにデプロイする
上記までの変更を github に push しておく。
vercel側で Add New ... > Project > Import Git Repository で連携してデプロイ。
詳細は割愛するが、vercel.jsonがあれば基本的に何もいじる項目はない。
注意としては、gitリポジトリのフォルダ構成として src/
の下に package.json やら vercel.json やらがある、みたいな場合は vercel の Settings > Root Directory に src
を指定しておく必要がある。
デプロイされたら、そのドメインのパスでAPI GETとかしてみてレスポンスとれたらOK。
json-server で POST リクエストにも固定のレスポンスだけ返したい
json-server 自体は POST や PUT でのリソースに更新にも対応している。
逆にいうと、POST とか PUT とかしちゃうとリソースが更新されちゃうので、何もせず固定の { "result":"success" }
みたいなレスポンスだけ返してほしい、という用途には使えない。
これをやりたければ、 server.js の中で単に API メソッドを POST -> GET に書き換えてやればいい。
参考)https://github.com/typicode/json-server/issues/453
// ~~(略)~~
server.use(function (req, res, next) {
if (req.method === 'POST') {
req.method = 'GET';
}
next();
})
server.use(router);
// ~~(略)~~