談到mock,就不得不講先後端分離。理想狀況下先後端不分離,由全棧的人以product和infrastructure的維度進行開發,效率是最高的。近些年來業務的複雜度愈來愈高,真正的全棧人才極爲難招,企業只能退而求其次,對開發進行分工細化,讓每一個人作本身最擅長的事,前端負責UI顯示和交互,後端負責業務的邏輯、性能等,從而架構上達到更高的效率。同時因爲分工的細化,致使先後端的溝通成本增長,代碼的控制權一般在後端,一次小的修改可能致使先後端反覆溝通,下降開發效率,就產生了先後端分離的方案。先後端分離經過約定好協議,使用約定的協議進行並行開發,將溝通最後階段放在聯調,節省了大量的時間。javascript
分離的表現主要是視圖層的控制交給前端,對於一些偏應用類項目,使用ajax請求,先後端各負責本身的部分,直接達到分離狀態,而一些展現類系統,受到seo和用戶體驗的影響,分離只能達到部分分離,如fis方案。不論是哪一種狀態的分離,都須要進行協議約定,以達到業務的並行開發。對於前端來講,開發的效果更多依賴於數據,想要最大程度的減小聯調時間,就須要根據協議生成數據,這也就是mock的需求。html
這裏借用yapi的流程圖(yapi表示mock服務):
前端
首先,先後端進行定製接口,定製完成後各自進行開發。前端的開發者使用mock數據進行開發,開發完成後進行真實環境的聯調,找出開發中的問題,再進行測試、上線等流程。java
直接數據寫在代碼中(或者獨立的文件,代碼中手動引入),修改代碼跳過接口請求,直接使用數據。這種方式的最大問題是耦合性太強,業務代碼中混雜了mock數據,每次正式提交都要保證代碼數據指向是正確的,不然會產生神奇的結果。同時不是真正發出網絡請求,和真實環境有差別。建議僅在沒有其餘方式的狀況下才使用。node
這種方式分爲攔截到本地和攔截到其餘服務器。相較於硬編碼,攔截式下降了mock數據和業務代碼的耦合性,只須要引入攔截的代碼,將請求轉發至本地,至本地文件或其餘服務器。這種方案的主要問題是須要針對代碼使用的各類庫進行定製插件,初期成本高;同時有部分的代碼入侵,須要保證入庫代碼正確。jquery
攔截至數據文件:
最典型的是Mock.js。這種方式實現了自由編寫數據,靈活性比較大,並且mock的數據文件能夠同步至倉庫中,下次開發時。缺點是一樣非網絡請求,真實性不足。webpack
攔截並改變請求:
這種方式之因此出現是由於服務器的URL和本機的URL規則不一樣,須要按照規則進行轉換。這種方式與真實狀況比較接近,同時產生了跨域,須要服務端提供對應的header。ios
這種方式在公用文件中直接添加接口前綴,依賴於特定的庫功能(或者達到相同效果的代碼結構)。同以前的攔截並改變請求相似,但更爲簡單一些,只改前綴就能夠了,一樣有代碼入侵的問題。nginx
這種方式分爲兩種:使用本地或軟件數據和代理轉發git
使用本地或軟件數據:
最經常使用的如:fiddler, charles, whistle等,能夠將請求返回指定內容。主要問題是配置比較繁瑣,全部操做都在本機,同步困難。
代理轉發:
這種方式和真實環境極爲接近,畢竟純靜態的文件,在服務端也是須要進行代理轉發的。可以使用的工具就比較多了,使用支持代理轉發的開發工具,或者使用上面提到的工具,一樣可以將數據轉發出去。這種方式最大的優勢是:無跨域、能發出真實請求、與業務代碼徹底隔離。
對比以上幾種方案,最優的選用代理轉發方式,其次是代碼攔截方式。攔截至數據文件有個優點就是能夠將mock數據和倉庫同步,但在不一樣分支開發時Mock數據可能會衝突。代理轉發和攔截至服務器使用最方便,但它須要mockServer。只視開發狀況而定。
mock的實現很是多,基本上每套完善的前端開發工具都是自帶mock的機制。近幾年隨着nodejs的流行,前端能夠很是方便的實現本身的mockServer,因此想列舉出全部的仍是很困難的,這裏介紹一些知名字較高的工具。
介紹: 提到mock,就不得不提到swagger (https://swagger.io/)。它是一個極爲流行的一個API設計開發工具,覆蓋了從設計到文檔到測試部署。它是這樣介紹的:
Swagger is the world’s largest framework of API developer tools for the OpenAPI Specification(OAS), enabling development across the entire API lifecycle, from design and documentation, to test and deployment.
在設計RESTFUL類型的API極爲有用,它沒有專門提供mock服務,但能夠提供mock服務的server模板代碼,可根據模板自行搭建mock-server。此外,還提供相關的API的JSON結構數據,配合相應的工具來實現相似的效果。
介紹:這款在國外用的比較多一些,功能也是比較強大:
Apiary.io平臺具備協同設計、即時API模擬、快速生成源碼、自動測試和代碼調試的開源設計工具,最重要的是能夠在線模擬測試,由於該平臺具有模擬服務器測試服務,能夠把設計好的程序在線測試、驗證。
介紹:這是去哪團隊作的,使用了nodejs+mongodb方式開發,主要特性:
- 基於 Json5 和 Mockjs 定義接口返回數據的結構和文檔,效率提高多倍
- 扁平化權限設計,即保證了大型企業級項目的管理,又保證了易用性
- 相似 postman 的接口調試
- 自動化測試, 支持對 Response 斷言
- MockServer 除支持普通的隨機 mock 外,還增長了 Mock 指望功能,根據設置的請求過濾規則,返回指望數據
- 支持 postman, har, swagger 數據導入
- 免費開源,內網部署,信息不再怕泄露了
有了各類極爲方便使用的mockServer,想要接入就很簡單了。mockServer的通常使用規則:
攔截式針對的是使用一些封裝過的ajax庫,好比jquery、axios,或者使用fetch庫。實現的方式各有不一樣。若是使用的是支持攔截器模式(如axios),攔截代碼就比較簡單了,直接在攔截器中改變URL指向便可,指向mockServer或mockjs文件。見如下代碼(如下代碼是摘自rap或rap2等其餘庫)。
function wrapAxios(axios) { var url = '' var oldRequest = {} var routePassed = false axios.interceptors.request.use(function (config) { url = config.url config.url = "http://" + ROOT + '/mockjsdata/' + projectId + url; oldRequest = Object.assign({}, config) return config; }, function (error) { return Promise.reject(error); }); axios.interceptors.response.use(function (res) { return res; }, function (error) { return Promise.reject(error); }); }
對於一些不支持攔截器的,或者原生的方法fetch,經過覆蓋的方式實現(https://github.com/wenlonghuo/rap2-delos/blob/master/public/libs/fetch.rap.js):
;(function (RAP, fetch) { if (!fetch) { console.warn('當前環境不支持 fetch') return } if (!RAP) { console.warn('請先引入 RAP 插件') return } let next = fetch let find = (settings) => { for (let repositoryId in RAP.interfaces) { for (let itf of RAP.interfaces[repositoryId]) { if (itf.method.toUpperCase() === settings.method.toUpperCase() && itf.url === settings.url) { return Object.assign({}, itf, { repositoryId }) } } } } window.fetch = function (url, settings) { // ajax(settings) if (typeof url === 'object') { settings = Object.assign({ method: 'GET' }, url) } else { // ajax(url) ajax(url, settings) settings = Object.assign({ method: 'GET' }, settings, { url }) } var match = find(settings) if (!match) return next.call(window, url, settings) let redirect = `${RAP.protocol}://${RAP.host}/app/mock/${match.repositoryId}/${match.method}/${match.url}` settings.credentials = 'include' settings.method = 'GET' settings.dataType = 'jsonp' console.log(`Fetch ${match.method} ${match.url} => ${redirect}`) return next.call(window, redirect, settings) } })(window.RAP, window.fetch)
使用這些插件的方法很簡單,直接在html最後添加指向的script標籤便可(部分攔截可能須要引入多個標籤)。
這種狀況適合mockServer請求中須要添加baseURL的類型。對於支持baseURL類型的庫,設置baseURL便可。如baseURL爲:
http://yapi.demo.qunar.com/mock/1304
咱們業務代碼中請求的api爲:
/weather/api
那麼咱們實際請求的地址是:
http://yapi.demo.qunar.com/mock/1304/weather/api
因此咱們應該這麼設置(以axios爲例):
export default axios = new Axios({ baseURL: process.env.NODE_ENV === 'development' ? 'http://yapi.demo.qunar.com/mock/1304' : })
若是是不區分環境的狀況下,須要在提交前將baseURL設置爲空,以避免影響倉庫代碼。
對於不支持baseURL的庫,建議封裝方法,單獨保存baseURL。
代理轉發實現的前提是你使用的開發工具支持轉發,若是不支持,就須要使用Fiddler、charles等工具進行規則重寫。下面舉一些例子:
webpack-dev-server中:
proxy: { "/api": "http://localhost:3000" } proxy: { "/api": { target: "http://localhost:3000", changeOrigin: true } }
注:changeOrigin是http-proxy設置選項,表示在請求頭中將host轉換爲目標服務器的地址或IP,解決服務器出現請求地址找不到的問題。
nginx(應該沒人用吧):
location /api { proxy_set_header X-Forwarded-Proto https; proxy_set_header Host $host; proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; proxy_pass http://localhost:11011; proxy_redirect off; }
fiddler中在右側的tab頁中選擇autoResponder標籤頁。編輯rule分別輸入
REGEX:^https://server\.example\.com/(.*) http://www.target.com:3838/$1
使用mock前提是先後端有一個明確的接口協議,利用合適的工具才能提升開發效率。強大的mock服務可使你對開發的代碼更爲自信,即便沒有後端,新手就能夠經過mock熟悉以前的業務界面,或者查看一些表現特殊的界面,最大程度減小對後端的依賴。
上面介紹的幾款mockServer有幾種都是使用nodejs開發的。和其餘語言開發的mock服務相比,json格式成爲書寫的主要格式,雖然用起來容易,但書寫上並不方便(json5格式在某種程度上加強了書寫體驗,但相比yaml等格式仍是有所不足)。同時業務狀況不一樣,針對性的選擇不一樣的平臺,推薦使用rap2和yapi,前者界面更爲簡潔,操做方便,後者功能更爲強大。若是有特殊的須要,能夠本身寫一個,順便練練手。
【你是如何構建 Web 前端 Mock Server 的? - 莫池宇的回答 - 知乎
https://www.zhihu.com/question/35436669/answer/235608128】