json-server的實踐與自定義配置化

天驅發表於2019-03-04

背景

之前做專案都沒有用到mock服務,都是等後端給介面欄位或者前端留空位;但新公司的專案需要搭建mock服務,本想把舊專案的json-server搬過來就好了,不過發現新增一個 mock api 步驟過於繁複,mock服務本應簡單為主,所以決定自己寫一個(本以為寫個 json 檔案就好了…)。

預期設計

按照我對mock服務的理解,只需檢測 restful 風格的 url 返回對應資料就好了,然後簡單看了下文件示例

1、建立db.json

{
  "posts": [
    { "id": 1, "title": "json-server", "author": "typicode" }
  ],
  "comments": [
    { "id": 1, "body": "some comment", "postId": 1 }
  ],
  "profile": { "name": "typicode" }
}
複製程式碼

2、啟動

$ json-server –watch db.json

3、訪問http://localhost:3000/posts/1

{ "id": 1, "title": "json-server", "author": "typicode" }
複製程式碼

哇這不是很簡單嗎(為自己埋坑),接下來只要將資料改造成路由的形式

// db.js
module.expors = {
    `/posts`: require(`./data/posts.json`),
    `/user/login`: require(`./data/user/login.json`),
    `/user/logout`: require(`./data/user/logout.json`)
}
複製程式碼

目錄結構

mock
|
└───data
|   |
|   └───posts.json
|   └───user
|       |
|       └───login.json
|       └───logout.json
|
└───db.js
└───server.js // 預期通過 node server.js 執行
複製程式碼

實踐一

編寫 server.js

const jsonServer = require(`json-server`)
const server = jsonServer.create()
const middlewares = jsonServer.defaults()

// Set default middlewares (logger, static, cors and no-cache)
server.use(middlewares)

// 獲取db資料
const db = require(`./db.js`)

// Use router
server.use(jsonServer.router(db))

server.listen(3000, () => {
  console.log(`JSON Server is running on 3000`)
})

複製程式碼

執行 node server.js 後報錯

/ aren`t supported, if you want to tweak default routes, see
https://github.com/typicode/json-server/#add-custom-routes
複製程式碼

看來是不支援路由風格db資料,那嘗試將db資料改成物件巢狀的模式,雖然這不夠直觀看出介面地址,但好歹也只是一個 json 檔案

// db.js
module.expors = {
    `posts`: require(`./data/posts.json`),
    `user`: {
        `login`: require(`./data/user/login.json`),
        `logout`: require(`./data/user/logout.json`)
    }
}
複製程式碼

這下可以執行了,開啟http://localhost:3000/user/login,誒怎麼是空物件{},日誌顯示GET /user/login 404 4.161 ms - 2;開啟http://localhost:3000/user,能夠顯示 login 和 logout 的資料,看來是當成/user介面了,那 json-server 怎麼返回/user/login的資料? 不支援路由風格就算了,連這個也不能讀取…

實踐二

看到有個jsonServer.rewriter方法,我們可以再次改寫db.jsserver.js

// db.js
module.expors = {
    `posts`: require(`./data/posts.json`),
    `user_login`: require(`./data/user/login.json`),
    `user_logout`: require(`./data/user/logout.json`)
}
複製程式碼
// server.js
... 省略部分程式碼

// 需要加在 server.use(router) 前
server.use(jsonServer.rewriter({
  `/user/login`: `/user_login`,
  `/user/logout`: `/user_logout`
}))
// Use router
server.use(jsonServer.router(db))

server.listen(3000, () => {
  console.log(`JSON Server is running on 3000`)
})
複製程式碼

這樣終於是可以正常執行mock服務了,雖然這有點醜,而且 json-server 本身只支援/posts/:id(根據 item 的指定 id 屬性選取),不支援/posts/:id/xxx這種寫法(需要手動新增jsonServer.rewriter

完善

當檔案越來越多的時候,手動新增db.jsjsonServer.rewriter是一種麻煩,所以需要自動根據檔案目錄生成dbjsonServer.rewriter,這樣我們新增 api 只需在合適的路徑新增 json 檔案(程式碼最後會附上地址)

疑惑

作為前端使用的mock服務,其實只需解決開發時獲取 get 請求資料的空白,避免先在頁面填充資料導致聯調時需要修改;再一個就是編寫足夠直觀、足夠簡單,在這一點上私以為 json-server 沒有做得很好(希望是我沒有領悟到 json-server 的使用方法),不能直觀的看出路由介面,不能很好的體現 restful api(需要新增jsonServer.rewriter)。

如果是我編寫一個mock服務的話,我可能會採用koakoa-router,只需編寫 get 路由介面

// router.js
router.get(`/posts`, () => require(`./data/posts.json`))
router.get(`/posts/:id`, () => require(`./data/posts/id.json`))
router.get(`/user/login`, () => require(`./data/user/login.json`))
router.get(`/user/logout`, () => require(`./data/user/logout.json`))
複製程式碼

ps:我知道 json-server 也有server.get方法,但這這樣似乎與db.json檔案衝突了

我會每一個介面都寫一個 json 檔案,這樣至少看起來很直觀,寫起來也足夠簡單,而且我手動實現 restful 比 json-server 不完全支援清晰很多;

總結

第一次實踐搭建 json-server,可能用法和理解上不太對,希望有問題可以指出;我把mock服務封裝到自己的 vue-cli template 上了,可以通過vue init masongzhi/vue-template-webpack my-project安裝,mock服務在/mock資料夾下。

ps:

相關文章:定製化vue-cli Template/webpack

相關文章