摘要:注意廣告警告廣告警告廣告警告在一個(gè)應(yīng)用的開發(fā)周期中一般前端與后端都是并行開發(fā)的各自完成自己的開發(fā)工作后進(jìn)行聯(lián)調(diào)聯(lián)調(diào)通過再進(jìn)行提測(cè)發(fā)布開發(fā)過程中前端都會(huì)以后端提供的文檔作為標(biāo)準(zhǔn)模擬返回?cái)?shù)據(jù)以確保在開發(fā)中就保證功能的完整性而關(guān)于如何更好的進(jìn)行業(yè)
注意! 廣告警告! 廣告警告! 廣告警告!
在一個(gè)web應(yīng)用的開發(fā)周期中, 一般前端與后端都是并行開發(fā)的, 各自完成自己的開發(fā)工作后進(jìn)行聯(lián)調(diào), 聯(lián)調(diào)通過再進(jìn)行提測(cè)/發(fā)布.
開發(fā)過程中, 前端都會(huì)以后端提供的 api 文檔作為標(biāo)準(zhǔn), mock 模擬 api 返回?cái)?shù)據(jù), 以確保在開發(fā)中就保證功能的完整性.
而關(guān)于如何更好的進(jìn)行 mock, 業(yè)界/開源社區(qū)可謂有相當(dāng)多質(zhì)量上乘的解決方案, 如easy-mock, yapi等.
但是越是大而全的工具很多時(shí)候功能會(huì)超越需求非常多, 要簡單實(shí)現(xiàn) mock api 的需求其實(shí)也有非常多小而美工具庫可以使用.
而本文主要介紹 mock-server 這個(gè)工具的使用
選用 mock-server 的主要原因除了是我開發(fā)的使用比較簡單之外, 更多的是滿足了下文提到的一些開發(fā)需求, 如果你也有同樣的需求而還沒找到解決方案的話, 不妨試用一下.
可選全局安裝, 安裝完成過后, 就可以通過mock命令啟動(dòng)來 mock server
npm install -g mock-server-local mock -h # 即安裝成功 # 用 -d 指定mock數(shù)據(jù)配置目錄, 為空時(shí)默認(rèn)為當(dāng)前目錄 `.` mock -d ./mock # 用 -p 指定server的端口, 默認(rèn)為8888, 如果8888被占用會(huì)端口號(hào)+1, 直至端口可用 # 注意如果指定了端口號(hào), 但是端口號(hào)被占用的話, 會(huì)拋出錯(cuò)誤 mock -d ./mock -p 8080
個(gè)人比較習(xí)慣在項(xiàng)目中進(jìn)行安裝, 并通過npm script啟動(dòng), 而 mock 數(shù)據(jù)也存放在項(xiàng)目當(dāng)中, 通過 git 等版本管理工具在項(xiàng)目成員當(dāng)中共享, 假設(shè)項(xiàng)目目錄為proj
// proj/package.json { // ... "script": { "mock": "mock -d ./mock -p 8080" } // ... }
# 本地安裝 npm install mock-server-local --save-dev # 啟動(dòng)mock server npm run mock > mock@1.8.9 mock /path/to/proj > mock -d ./mock -p 8080 you can access mock server: http://127.0.0.1:8080 http://ww.xx.yy.zz:8080 you can access mock server view: http://127.0.0.1:8080/view http://ww.xx.yy.zz:8080/view
就這樣 mock server 就已經(jīng)啟動(dòng)了, 訪問127.0.0.1:8080/view即可看到 mock server 的控制頁面
就下來就是調(diào)整代理, 把應(yīng)用的請(qǐng)求轉(zhuǎn)發(fā)到 mock server 進(jìn)行處理
如果你使用webpack來構(gòu)建你的項(xiàng)目, 那你只需要改動(dòng)一下webpack.devServer的配置即可
假設(shè)我們的業(yè)務(wù)域名為target.mock.com, 而接口基本都是target.mock.com/api/**, 可以這樣進(jìn)行配置
devServer: { proxy: { "/api": { target: "http://127.0.0.1:8080", // mock server headers: { host: "target.mock.com" // 業(yè)務(wù)域名 }, onProxyReq: function(proxyReq, req, res) { proxyReq.setheader("host", "target.mock.com"); // 業(yè)務(wù)域名 } } } }
接著在開發(fā)中, 啟動(dòng) webpack 之后, 發(fā)出的請(qǐng)求/api/**都會(huì)被轉(zhuǎn)發(fā)到
而如果應(yīng)用本身不使用 webpack 或其他帶 server 功能的打包工具, 可以使用代理工具進(jìn)行請(qǐng)求轉(zhuǎn)發(fā)
如果是用 Chrome 瀏覽器調(diào)試應(yīng)用, 可以下載SwitchyOmega一類可配置, 把特定域名的請(qǐng)求進(jìn)行轉(zhuǎn)發(fā)
使用微信開發(fā)者工具的話, 可直接設(shè)置代理, 設(shè)置 -> 代理設(shè)置 -> 勾選手動(dòng)設(shè)置代理 -> 填寫代理配置
推薦使用 whistle, fiddler 一類功能完整代理工具, 類似配置如下
target.mock.com/api 127.0.0.1:8080 # 接口請(qǐng)求轉(zhuǎn)發(fā)到mock server target.mock.com www.xx.yy.zz # 頁面從正常的開發(fā)測(cè)試機(jī)ip中獲取, 或本地調(diào)試服務(wù)器mock 數(shù)據(jù)配置
mock server 的配置是根據(jù) mock 目錄的目錄結(jié)構(gòu)生成的, 假設(shè)需要進(jìn)行 mock 的 api 接口完整的 url 為target.mock.com/api/login
而且需要模擬以下三種情況的數(shù)據(jù)返回
登錄失敗, 返回錯(cuò)誤碼-1 及錯(cuò)誤信息
登錄成功, 返回錯(cuò)誤碼 0 和用戶信息, 且要帶上登錄態(tài) cookie
請(qǐng)求時(shí)間超過 8 秒, 導(dǎo)致前端請(qǐng)求超時(shí)
那么目錄結(jié)構(gòu)與數(shù)據(jù)配置文件應(yīng)該如下所示
|- proj |- mock |- target.mock.com |- api |- login |- 登錄成功 |- 登錄失敗 |- 請(qǐng)求超時(shí) // 登錄失敗 // proj/mock/target.mock.com/api/login/登錄失敗/data.js module.exports = { code: -1, msg: "登錄失敗!" }; // 登錄成功 // proj/mock/target.mock.com/api/login/登錄成功/data.js module.exports = { code: 0, msg: "登錄成功", username: "ahui" }; // proj/mock/target.mock.com/api/login/登錄成功/http.js module.exports = { header: { "Set-Cookie": "token=123456789;" } }; // 請(qǐng)求超時(shí) // proj/mock/target.mock.com/api/login/請(qǐng)求超時(shí)/data.js module.exports = {}; // proj/mock/target.mock.com/api/login/請(qǐng)求超時(shí)/http.js module.exports = { delay: 8 };
根據(jù)上面目錄配置, 訪問 mock server 頁面的 mock 面板127.0.0.1:8080/view/mocks, 就可以看到以下頁面
現(xiàn)在我們只需要勾選其中一個(gè)狀態(tài), 然后發(fā)出請(qǐng)求即可
mock完成之后就可以愉快編寫業(yè)務(wù)邏輯了
mock 配置詳解看了上面的例子應(yīng)該也就大致可以了解到, data.js里面定義接口返回的數(shù)據(jù). 而http.js, 顧名思義就是定義 http 請(qǐng)求相關(guān)行為的, 例如可以定義響應(yīng)頭, http 狀態(tài)碼, 請(qǐng)求耗時(shí)等.
data 同時(shí)也支持使用 json 文件, 非 js/json 文件的一律當(dāng) json 格式處理, 而 http 則只支持通過 js 文件定義
http.js可選配置如下
module.exports = { delay: 8, // 耗時(shí)8秒 status: 200 // http狀態(tài)碼 header: { // ... http響應(yīng)頭 } }
而data.js除了可以簡單定義返回?cái)?shù)據(jù)之外, 還可以直接返回模板, 如
module.exports = `Document 這個(gè)是由mock server返回的模板 `;
并且可以返回一個(gè)方法, 通過腳本邏輯來處理最終要返回的數(shù)據(jù)
// ctx: https://koajs.com/#context module.exports = function(ctx) { // 邏輯處理 return { data: {}, // 響應(yīng)數(shù)據(jù) header: {}, // 如有需要可以配置, 同http.js#header delay: 0.1, // 如有需要可以配置, 同http.js#delay status: 200 // 如有需要可以配置, 同http.js#status }; }; // 如果當(dāng)中有異步邏輯, 請(qǐng)返回promise, 或直接使用async方法 module.exports = async function(ctx) { // 異步邏輯處理 await asyncFn(); return { data: {}, // 響應(yīng)數(shù)據(jù) header: {}, // 如有需要可以配置, 同http.js#header delay: 0.1, // 如有需要可以配置, 同http.js#delay status: 200 // 如有需要可以配置, 同http.js#status }; };代理線上數(shù)據(jù)
在開發(fā)過程可能出現(xiàn)這樣的場(chǎng)景, 一期項(xiàng)目已經(jīng)開發(fā)完了, 現(xiàn)在進(jìn)行二期迭代的開發(fā)工作, 這個(gè)時(shí)候由于之前的接口后臺(tái)已經(jīng)都實(shí)現(xiàn), 二期開發(fā)中只想對(duì)新增的 api 進(jìn)行 mock
這個(gè)時(shí)候可以修改一下代理工具的配置, 把不同接口的請(qǐng)求轉(zhuǎn)發(fā)到不同的服務(wù)器
# 新增接口轉(zhuǎn)發(fā)至mock server target.mock.com/api/new1 127.0.0.1:8080 target.mock.com/api/new2 127.0.0.1:8080 # 其余接口直接使用線上/測(cè)試機(jī)數(shù)據(jù) target.mock.com ww.xx.yy.zz
又或者可以直接使用 mock server 提供的簡單的代理功能, 只需要在 mock 目錄個(gè)目錄下新建proxy.js文件
|- proj |- mock |- proxy.js // proj/mock/proxy.js module.exports = { target.mock.com: "https://ww.xx.yy.zz" // 這里可以指定ip也可以指定域名, 但是需要注意協(xié)議類型是必須要帶上的 }
這樣配置之后, 在代理工具中就可以直接把所有的target.mock.com的請(qǐng)求都直接轉(zhuǎn)發(fā)到 mock server
當(dāng)對(duì)應(yīng)請(qǐng)求的 url 并沒有勾選任何一個(gè)返回狀態(tài), 或根本沒有配置對(duì)應(yīng)的 url 時(shí), mock server 都會(huì)幫助我們把請(qǐng)求轉(zhuǎn)發(fā)到目標(biāo) ip
假設(shè)沒有配置proxy.js的話, 對(duì)于沒有命中的 url 請(qǐng)求, 會(huì)根據(jù) host 直接請(qǐng)求線上的資源或接口
模板接口調(diào)試 & 微信登錄支持在非前后端分離的架構(gòu)中, 很常會(huì)出現(xiàn)這樣的需求, 應(yīng)用的入口即是后端接口, 后端會(huì)進(jìn)行鑒權(quán), 拼接模板內(nèi)容和數(shù)據(jù), 然后直接返回頁面給到前端進(jìn)行展示.
這樣的場(chǎng)景 mock server 可以很簡單通過data.js中導(dǎo)出方法的方式來處理
const fs = require("fs"); module.exports = async ctx => { let html = ""; let template = fs.readFileSync("path/to/html/template/index.ejs"); // 舉例ejs, 實(shí)際可以處理任何模板引擎 // 這里處理模板的語法 // 1. 處理類似include的拼接模板的語法 // 2. 處理類似<%= =>插入變量/數(shù)據(jù)的語法 // 3. 等等等等.... html = processedHtml; return { data: html, header: { "Set-Cookie": "SESSIONID=123123123123;" }; }; };
這樣子我們就可以進(jìn)行模板接口的調(diào)試了. 再回到我們的上一個(gè)例子
我們希望可以使用線上已有接口和數(shù)據(jù)狀態(tài)(如開戶數(shù)據(jù))
也希望使用后端的登錄態(tài)(這樣后續(xù)的接口調(diào)用也能通過鑒權(quán)), 但也同時(shí)希望可以調(diào)試本地模板呢?
比較直觀的方式是, 本地修改模板然后把模板改動(dòng)上傳到開發(fā)服務(wù)器, 然后直接請(qǐng)求開發(fā)服務(wù)器進(jìn)行調(diào)試
但是改動(dòng)比較多, 需要頻繁調(diào)試的話, 或許使用 mock server 也是一個(gè)不錯(cuò)的選擇. 更進(jìn)一步, 如果是微信 h5 且后端的登錄鑒權(quán)接入了微信登錄呢?
我們來分析一下如何使用 mock server 滿足這樣的調(diào)試述求, h5 微信登錄基本的流程如下
請(qǐng)求線上/開發(fā)測(cè)試服務(wù)器接口
接口返回 http 狀態(tài)碼 302 并帶上 Location 頭, 跳轉(zhuǎn)到微信 url
請(qǐng)求微信 url 會(huì)返回 301 再回跳我們的業(yè)務(wù)域名
回跳我們的業(yè)務(wù)域名時(shí), 即再次請(qǐng)求服務(wù)器接口, 獲取微信登錄 code 進(jìn)行業(yè)務(wù)登錄
返回登錄態(tài)及 html 頁面
上面的流程中, 其實(shí)需要介入只有最后一步而已, 就是獲取到登錄態(tài)并返回需要調(diào)試的 html 模板內(nèi)容即可
而前面的步驟, 完全可以通過在data.js中實(shí)現(xiàn)簡單的代理完成
// 微信登錄/data.js const httpProxy = require("http-proxy"); const fs = require("fs"); const path = require("path"); proxy = httpProxy.createServer({ secure: false }); async function req({ req, res }) { proxy.web(req, res, { target: { protocol: "https:", host: "ww.xx.yy.zz", // 目標(biāo)服務(wù)器 port: 443, pfx: fs.readFileSync(path.resolve(process.cwd(), "cert/cert.p12")), // 如果服務(wù)器是https需要生成證書 passphrase: "password" }, selfHandleResponse: true }); return new Promise((resolve, reject) => { proxy.once("proxyRes", function(proxyRes, req, res) { let body = []; let size = 0; function onData(chunk) { body.push(chunk); size += chunk.length; } proxyRes.on("data", onData).once("end", () => { proxyRes.off("data", onData); body = Buffer.concat(body, size); resolve({ header: proxyRes.headers, data: body, status: proxyRes.statusCode }); }); }); }); } module.exports = async function(ctx) { // 登錄態(tài) const res = await req(ctx); const header = res.header; res.header = Object.keys(header).reduce((c, k) => { let nk = k .split("-") .map(v => v.charAt(0).toUpperCase() + v.slice(1)) .join("-"); c[nk] = header[k]; return c; }, {}); if (res.header["Set-Cookie"]) { // 如果有Set-Cookie header, 則要處理返回本地模板 // 這里處理模板的語法 // 1. 處理類似include的拼接模板的語法 // 2. 處理類似<%= =>插入變量/數(shù)據(jù)的語法 // 3. 等等等等.... res.data = template; // 這里需要注意, 目標(biāo)服務(wù)器可能會(huì)返回gzip過后的數(shù)據(jù) // 如果不對(duì)Content-Encoding和Content-Length進(jìn)行處理的話 // 會(huì)導(dǎo)致響應(yīng)中Content-Length和實(shí)際內(nèi)榮長度不一致而出錯(cuò) res.header["Content-Encoding"] = "identity"; delete res.header["Content-Length"]; } return res; };
這樣我們就可以對(duì)具體的接口模板進(jìn)行調(diào)試了
寫在最后重復(fù)造輪子不易, 且造且珍惜
如果大家有mock api的需求的話, 不妨也試用一下 mock-server
如果覺得 mock-server 還不錯(cuò), 或者解決了mock的一些痛點(diǎn), 不妨賞個(gè)star
最后, 用得不爽或發(fā)現(xiàn)bug, 懇請(qǐng)?zhí)醝ssue!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/109613.html
摘要:如何去解決這些問題前后端分離大部分的互聯(lián)網(wǎng)公司都分成了前端團(tuán)隊(duì)和后端團(tuán)隊(duì)。方案一采用架構(gòu)業(yè)界很多公司會(huì)采用,單頁應(yīng)用的架構(gòu),這種架構(gòu)是天然的前后端分離的。方案二淘寶的大前端方案中途島上圖是淘寶基于的前后端分離分層,以及的職責(zé)范圍。 我們遇到了什么問題? 1.前端無法調(diào)試后端未完成的 API:如果后端同學(xué)還沒有完成 API 開發(fā),那么前端同學(xué)就不能對(duì)這個(gè) API 進(jìn)行開發(fā)。之前我們都是在...
摘要:采用前后端分離模式可以減后臺(tái)負(fù)擔(dān),加快研發(fā)效率,當(dāng)然,前提是前端能做好的話。還是基礎(chǔ)不夠?qū)е碌暮蠖耸欠耧L(fēng)格很多公司采用了前后端分離模式后,后端仍然采用以往的傳統(tǒng)風(fēng)格,這是不合理的,風(fēng)格的應(yīng)該是前后端分離的最佳實(shí)踐。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web開發(fā)是不分前端后端的?;ヂ?lián)網(wǎng)進(jìn)入Web2.0時(shí)...
摘要:采用前后端分離模式可以減后臺(tái)負(fù)擔(dān),加快研發(fā)效率,當(dāng)然,前提是前端能做好的話。還是基礎(chǔ)不夠?qū)е碌暮蠖耸欠耧L(fēng)格很多公司采用了前后端分離模式后,后端仍然采用以往的傳統(tǒng)風(fēng)格,這是不合理的,風(fēng)格的應(yīng)該是前后端分離的最佳實(shí)踐。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web開發(fā)是不分前端后端的。互聯(lián)網(wǎng)進(jìn)入Web2.0時(shí)...
摘要:采用前后端分離模式可以減后臺(tái)負(fù)擔(dān),加快研發(fā)效率,當(dāng)然,前提是前端能做好的話。還是基礎(chǔ)不夠?qū)е碌暮蠖耸欠耧L(fēng)格很多公司采用了前后端分離模式后,后端仍然采用以往的傳統(tǒng)風(fēng)格,這是不合理的,風(fēng)格的應(yīng)該是前后端分離的最佳實(shí)踐。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web開發(fā)是不分前端后端的?;ヂ?lián)網(wǎng)進(jìn)入Web2.0時(shí)...
摘要:前后端的界限是按照瀏覽器和服務(wù)器的劃分。前后端彼此互不關(guān)聯(lián)。關(guān)于作者本文部分圖片段落參考文章實(shí)踐中的前后端分離。淘寶前后端分離實(shí)踐本文源碼詳見服務(wù)端代碼。 一、起源 (故事純屬虛構(gòu),如有雷同,純屬巧合)傳說在很久很久以前,我們有志之士有了個(gè)創(chuàng)業(yè)的想法,于是乎開始了自己的創(chuàng)業(yè)之夢(mèng),但是人手不足啊,于是乎所有角色老子一個(gè)人全包了: Roles: PM, DBA, RD, FED, Des...
閱讀 3787·2021-11-17 09:33
閱讀 2857·2021-09-22 15:12
閱讀 3412·2021-08-12 13:24
閱讀 2518·2019-08-30 11:14
閱讀 1793·2019-08-29 14:09
閱讀 1378·2019-08-26 14:01
閱讀 3140·2019-08-26 13:49
閱讀 1835·2019-08-26 12:16