前端使用Mock服務Json-server

前言

因爲Jaguar服務目前尚未任何的API輸出,一邊寫前端功能,一邊寫後端API顯然不利於總體的項目進展。因此我計劃先定義好接口,而後將全部的API都先部署在一個Mock服務器上,等前端界面和功能流程徹底走通後,再轉過頭來在Jaguar上編寫對應的API。
說到這裏,不由想到先後端協做一直存在的一個效率瓶頸。前端

先後端協做的效率瓶頸

在前(客戶端)後端協做開發中,有很多影響效率的地方,其中最爲典型的就是:node

  1. 前端的界面和功能中,由於存在很多功能依賴後端數據接口的,因此須要等待後端給出。
  2. 後端接口給出後,因爲初期設計不合理,或聯調中遇到特殊狀況,或需求有變更,致使須要改寫部分接口邏輯,因此須要等待並從新聯調。

雖然每次等待的時間也許不長,可是這樣的等待多了以後,勢必會形成開發時間變得支離破碎,開發流程經常中斷,而一旦中斷,從新進入開發狀態也須要花必定的時間,相信你們對此都有所體會。
其帶來的嚴重後果就是,時間一點一點被浪費掉了,實際的開發時間比預計的要長出很多,更慘的是因爲項目的工期以前已經定好,因此你們就只能加班了,因爲這樣的「教訓」,你們在下次估算時間的時候,每每會增長更多的Buffer,從而致使整個團隊的效率下降。webpack

理想狀況

那麼上面的這種狀況可否避免呢?答案是確定的。關於先後端協做的理想狀態,我認爲是:ios

開始前

在項目開始前各個端的開發同窗坐在一塊兒幹兩件事:git

  1. 討論並定義好涉及到的接口,接口中須要的參數,字段,類型及各類狀態處理
  2. 造成一份接口文檔供多方使用

開發中

到此爲止,雙方分開,前端去寫UI部分的功能,涉及到後端接口的所有由Mock服務給出,前端在Mock服務中增長本身所須要的各類Json數據,模擬各類狀態的邏輯處理。github

聯調階段

最後聯調時將Mock服務的地址換成後端聯調環境的地址,便可完成所有功能,中間不存在等待的狀況。因爲雙方都不會被打斷,團隊效率由此提高。web

固然,我描述的狀況過於理想,在開發工程中不免會遇到不清楚或雙方都沒有考慮到的問題,須要隨時溝通的,即使是這樣,溝通清楚後前端修改Mock接口,後端修改業務接口便可,也不存在互相等待的狀況,效率依然能有顯著的提高。npm

Mock服務

若是要達到以上描述的理想狀況,前端同窗須要在開發中引入Mock服務,這樣能夠最大限度的不依賴後端輸出,從而避免了等待。
一個標準的Mock服務須要知足以下條件:json

  1. 提供可以快速部署的基礎Http服務
  2. 可以方便而靈活的配置路由,最好提供Restful支持
  3. 可以方便的製造Mock數據
  4. 可以處理簡單業務邏輯

JSON Server

這裏推薦一款很是強大的Mock服務-JSON Server
https://github.com/typicode/json-server
JSON Server除了知足以上4點外,還能夠:後端

  1. 支持路由參數過濾數據
  2. 支持分頁,排序和全文搜索
  3. 支持JSONP,支持Https
  4. 支持兩級路由資源嵌套

除此以外,更加使人驚喜的是,其可以和webpack作到無縫集成,能夠經過配置和npm server一塊兒啓動,安裝方法很簡單,再也不贅述。配置方法以下:

第一步

在項目的根目錄下建立一個mock文件夾,而後在裏面增長一個db.json文件,在裏面寫入全部的mock數據,好比:

{
  "boardList": [
    {
      "title": "開放產品",
      "description": "開放產品是一款開放產品",
      "id": "car",
      "toKey": "analysis",
      "saleout": false
    },
    {
      "title": "品牌營銷",
      "description": "品牌營銷幫助你的產品更好地找到定位",
      "id": "earth",
      "toKey": "count",
      "saleout": false
    },
    {
      "title": "使命必達",
      "description": "使命必達快速迭代永遠保持最前端的速度",
      "id": "loud",
      "toKey": "forecast",
      "saleout": true
    },
    {
      "title": "勇攀高峯",
      "description": "幫你勇闖高峯,到達事業的頂峯",
      "id": "hill",
      "toKey": "publish",
      "saleout": false
    }
  ]}

第二步

在package.json中的script中增長命令mock和mockdev:

"scripts": {
    "dev": "node build/dev-server.js",
    "start": "node build/dev-server.js",
    "build": "node build/build.js",
    "mock": "json-server mock/db.json --port 9090", // 配置db路徑和端口
    "mockdev": "npm run mock & npm run dev",
  },

這樣就能夠經過npm run mockdev的方式同時啓動npm服務和mock服務了。

第三步

在config下的index.js中,增長proxyTable,將全部api請求轉發到mock server上

proxyTable: { // proxy all requests starting with /api to jsonplaceholder
      '/api': {
        target: 'http://localhost:9090',
        changeOrigin: true,
        secure: false,
        pathRewrite: {
          '^/api': ''
        }
      }
    },

進階

若是是一個簡單的項目,以上的三步基本知足了對mock服務的基本要求,可是稍微複雜些的項目每每會遇到以下幾個狀況:

  1. 默認狀況下JSON Server啓動命令中只能帶一個db.json,而實際項目中,若是全部接口數據都寫在一個json文件中,顯然不利於維護,最好每類接口對應一個json文件,以下圖

  1. 一般狀況下,接口返回的數據不只包含業務數據,還包含狀態數據和錯誤消息,一個常見的接口返回數據格式以下:
{
    data: {}, //業務數據
    status: 0,
    msg: ''
  }

那麼不可能把這些數據寫在每一個mock接口中,維護起來成本過高,因此須要找一個地方統一處理。

爲了解決以上兩個問題,首先建立一個server.js文件,在裏面編寫對應的邏輯:

const jsonServer = require('json-server')
const server = jsonServer.create()

// Support middleware
const middleware = jsonServer.defaults()
server.use(middleware)

// 支持加載多個db json文件
const _ = require('underscore')
const path = require('path')
const fs = require('fs')
const mockDir = path.join(__dirname, 'data')
const base = {}
const files = fs.readdirSync(mockDir)
files.forEach(function (file) {
  _.extend(base, require(path.resolve(mockDir, file)))
})
const router = jsonServer.router(base)
server.use(router)

// 返回自定義格式數據
router.render = (req, res) => {
  console.log(res.locals.data)
  res.jsonp({
    data: res.locals.data,
    status: 0,
    msg: ''
  })
}

server.listen(9090, () => {
  console.log('JSON Server is running')
})

同時,修改package.json中的script爲:

"scripts": {
    "dev": "node build/dev-server.js",
    "start": "node build/dev-server.js",
    "build": "node build/build.js",
    "mock": "node mock/server.js", 
    "mockdev": "npm run mock & npm run dev",
  },

除此以外,簡單的數據校驗,用戶權限驗證等邏輯也能夠寫到server.js中,如:

server.use((req, res, next) => {
 if (isAuthorized(req)) { // add your authorization logic here
   next() // continue to JSON Server router
 } else {
   res.sendStatus(401)
 }
})

Post請求

對於Post請求,須要在server.js中進行處理,好比:訪問登陸接口/account/login以後,返回當前登陸用戶的信息。
首先在db中增長返回的信息內容:

"login": {
    "id": 33,
    "name": "邢天宇",
    "avatar_url": "https://adminlte.io/themes/AdminLTE/dist/img/user2-160x160.jpg",
    "created_at": "17 Aug 16:22",
    "platform": "ios"
  },

而後在server.js中增長以下代碼:

// 處理登陸邏輯
server.post('/account/login', function (req, res) {
  let db = router.db 
  let data = db.get('login').value() //這裏的login就是db中的key
  res.jsonp({
    data: data,
    status: 0,
    message: ''
  })
})

 

這是再次運行npm run mockdev時會發如今mock/data/文件夾內會產生一個db.json的文件,能夠將須要的內容貼到文件內部,而後經過調用就能夠達到訪問的目的了。

 

 

本文摘抄於https://www.jianshu.com/p/7094c477207d     

相關文章
相關標籤/搜索