本文是Vue實戰(zhàn)系列的第三篇文章看峻,主要介紹Falcon項目所依賴的Mock服務(wù)JSON Server屑那。
Falcon項目地址:https://github.com/thierryxing/Falcon
前言
由于Jaguar服務(wù)目前還沒有任何的API輸出撒顿,一邊寫前端功能扯再,一邊寫后端API顯然不利于整體的項目進(jìn)展离熏。所以我計劃先定義好接口佳谦,然后將所有的API都先部署在一個Mock服務(wù)器上,等前端界面和功能流程完全走通后滋戳,再轉(zhuǎn)過頭來在Jaguar上編寫對應(yīng)的API钻蔑。
說到這里,不禁想到前后端協(xié)作一直存在的一個效率瓶頸奸鸯。
前后端協(xié)作的效率瓶頸
在前(客戶端)后端協(xié)作開發(fā)中咪笑,有不少影響效率的地方,其中最為典型的就是:
- 前端的界面和功能中娄涩,因為存在不少功能依賴后端數(shù)據(jù)接口的窗怒,所以需要等待后端給出。
- 后端接口給出后蓄拣,由于初期設(shè)計不合理扬虚,或聯(lián)調(diào)中遇到特殊情況,或需求有變動球恤,導(dǎo)致需要改寫部分接口邏輯辜昵,所以需要等待并重新聯(lián)調(diào)。
雖然每次等待的時間也許不長咽斧,但是這樣的等待多了之后堪置,勢必會造成開發(fā)時間變得支離破碎躬存,開發(fā)流程常常中斷,而一旦中斷舀锨,重新進(jìn)入開發(fā)狀態(tài)也需要花一定的時間岭洲,相信大家對此都有所體會。
其帶來的嚴(yán)重后果就是雁竞,時間一點一點被浪費掉了钦椭,實際的開發(fā)時間比預(yù)計的要長出不少,更慘的是由于項目的工期之前已經(jīng)定好碑诉,所以大家就只能加班了彪腔,由于這樣的“教訓(xùn)”,大家在下次估算時間的時候进栽,往往會增加更多的Buffer德挣,從而導(dǎo)致整個團(tuán)隊的效率降低。
理想情況
那么上面的這種情況能否避免呢快毛?答案是肯定的格嗅。關(guān)于前后端協(xié)作的理想狀態(tài),我認(rèn)為是:
開始前
在項目開始前各個端的開發(fā)同學(xué)坐在一起干兩件事:
- 討論并定義好涉及到的接口唠帝,接口中需要的參數(shù)屯掖,字段,類型及各種狀態(tài)處理
- 形成一份接口文檔供多方使用
開發(fā)中
到此為止襟衰,雙方分開贴铜,前端去寫UI部分的功能,涉及到后端接口的全部由Mock服務(wù)給出瀑晒,前端在Mock服務(wù)中增加自己所需要的各種Json數(shù)據(jù)绍坝,模擬各種狀態(tài)的邏輯處理。
聯(lián)調(diào)階段
最后聯(lián)調(diào)時將Mock服務(wù)的地址換成后端聯(lián)調(diào)環(huán)境的地址苔悦,即可完成全部功能轩褐,中間不存在等待的情況。由于雙方都不會被打斷玖详,團(tuán)隊效率由此提升把介。
當(dāng)然,我描述的情況過于理想蟋座,在開發(fā)工程中難免會遇到不清楚或雙方都沒有考慮到的問題劳澄,需要隨時溝通的,即便是這樣蜈七,溝通清楚后前端修改Mock接口秒拔,后端修改業(yè)務(wù)接口即可,也不存在互相等待的情況,效率依然能有顯著的提升砂缩。
Mock服務(wù)
如果要達(dá)到以上描述的理想情況作谚,前端同學(xué)需要在開發(fā)中引入Mock服務(wù),這樣可以最大限度的不依賴后端輸出庵芭,從而避免了等待妹懒。
一個標(biāo)準(zhǔn)的Mock服務(wù)需要滿足如下條件:
- 提供能夠快速部署的基礎(chǔ)Http服務(wù)
- 能夠方便而靈活的配置路由,最好提供Restful支持
- 能夠方便的制造Mock數(shù)據(jù)
- 能夠處理簡單業(yè)務(wù)邏輯
JSON Server
這里推薦一款非常強(qiáng)大的Mock服務(wù)-JSON Server
https://github.com/typicode/json-server
JSON Server除了滿足以上4點外双吆,還可以:
- 支持路由參數(shù)過濾數(shù)據(jù)
- 支持分頁眨唬,排序和全文搜索
- 支持JSONP,支持Https
- 支持兩級路由資源嵌套
除此之外好乐,更加令人驚喜的是匾竿,其能夠和webpack做到無縫集成,可以通過配置和npm server一起啟動蔚万,安裝方法很簡單岭妖,不再贅述。配置方法如下:
第一步
在項目的根目錄下創(chuàng)建一個mock文件夾反璃,然后在里面增加一個db.json文件昵慌,在里面寫入所有的mock數(shù)據(jù),比如:
"projects": [
{
"id": 4,
"title": "Gengmei",
"icon": "http://git.gengmei.cc/uploads/project/avatar/310/512-new.png",
},
"environments": [
{
"id": 1,
"name": "Production",
"projectId": 4
},
{
"id": 2,
"name": "Test",
"projectId": 4
}
]]
第二步
在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服務(wù)和mock服務(wù)了淮蜈。
如果我想訪問第一步中配置的projects列表斋攀,那么地址為:
訪問id為4的project,地址為:
由于支持路由資源嵌套梧田,而environments下存在projectId為4的對象淳蔼,所以訪問id為4的project下的environments地址為:
第三步
在config下的index.js中,增加proxyTable柿扣,將所有api請求轉(zhuǎn)發(fā)到mock server上
proxyTable: { // proxy all requests starting with /api to jsonplaceholder
'/api': {
target: 'http://localhost:9090',
changeOrigin: true,
secure: false,
pathRewrite: {
'^/api': ''
}
}
},
進(jìn)階
如果是一個簡單的項目,以上的三步基本滿足了對mock服務(wù)的基本要求闺魏,但是稍微復(fù)雜些的項目往往會遇到如下幾個情況:
- 默認(rèn)情況下JSON Server啟動命令中只能帶一個db.json未状,而實際項目中,如果所有接口數(shù)據(jù)都寫在一個json文件中析桥,顯然不利于維護(hù)司草,最好每類接口對應(yīng)一個json文件,如下圖
- 通常情況下泡仗,接口返回的數(shù)據(jù)不僅包含業(yè)務(wù)數(shù)據(jù)埋虹,還包含狀態(tài)數(shù)據(jù)和錯誤消息,一個常見的接口返回數(shù)據(jù)格式如下:
{
data: {}, //業(yè)務(wù)數(shù)據(jù)
status: 0,
msg: ''
}
那么不可能把這些數(shù)據(jù)寫在每個mock接口中娩怎,維護(hù)起來成本太高搔课,所以需要找一個地方統(tǒng)一處理。
為了解決以上兩個問題截亦,首先創(chuàng)建一個server.js文件爬泥,在里面編寫對應(yīng)的邏輯:
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)
// 返回自定義格式數(shù)據(jù)
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",
},
除此之外,簡單的數(shù)據(jù)校驗袍啡,用戶權(quán)限驗證等邏輯也可以寫到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中進(jìn)行處理境输,比如:訪問登錄接口/account/login之后蔗牡,返回當(dāng)前登錄用戶的信息。
首先在db中增加返回的信息內(nèi)容:
"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: ''
})
})
關(guān)于JSON Server完整的例子在此:
https://github.com/thierryxing/Falcon/tree/mock
結(jié)語
經(jīng)過本人及團(tuán)隊內(nèi)部實際使用嗅剖,前端同學(xué)完全可以在不依賴后端的情況下辩越,完成所有的界面和功能編寫。
下一步窗悯,準(zhǔn)備將其推廣到移動客戶端團(tuán)隊中使用区匣。