利用mock提升效率

利用mock提升效率

談到mock,就不得不講先後端分離。理想狀況下先後端不分離,由全棧的人以product和infrastructure的維度進行開發,效率是最高的。近些年來業務的複雜度愈來愈高,真正的全棧人才極爲難招,企業只能退而求其次,對開發進行分工細化,讓每一個人作本身最擅長的事,前端負責UI顯示和交互,後端負責業務的邏輯、性能等,從而架構上達到更高的效率。同時因爲分工的細化,致使先後端的溝通成本增長,代碼的控制權一般在後端,一次小的修改可能致使先後端反覆溝通,下降開發效率,就產生了先後端分離的方案。先後端分離經過約定好協議,使用約定的協議進行並行開發,將溝通最後階段放在聯調,節省了大量的時間。javascript

分離的表現主要是視圖層的控制交給前端,對於一些偏應用類項目,使用ajax請求,先後端各負責本身的部分,直接達到分離狀態,而一些展現類系統,受到seo和用戶體驗的影響,分離只能達到部分分離,如fis方案。不論是哪一種狀態的分離,都須要進行協議約定,以達到業務的並行開發。對於前端來講,開發的效果更多依賴於數據,想要最大程度的減小聯調時間,就須要根據協議生成數據,這也就是mock的需求。html

使用mock開發流程

這裏借用yapi的流程圖(yapi表示mock服務):
前端

首先,先後端進行定製接口,定製完成後各自進行開發。前端的開發者使用mock數據進行開發,開發完成後進行真實環境的聯調,找出開發中的問題,再進行測試、上線等流程。java

經常使用的mock方式

1. 代碼層硬編碼

直接數據寫在代碼中(或者獨立的文件,代碼中手動引入),修改代碼跳過接口請求,直接使用數據。這種方式的最大問題是耦合性太強,業務代碼中混雜了mock數據,每次正式提交都要保證代碼數據指向是正確的,不然會產生神奇的結果。同時不是真正發出網絡請求,和真實環境有差別。建議僅在沒有其餘方式的狀況下才使用。node

2. 代碼中針對使用的ajax庫攔截

這種方式分爲攔截到本地和攔截到其餘服務器。相較於硬編碼,攔截式下降了mock數據和業務代碼的耦合性,只須要引入攔截的代碼,將請求轉發至本地,至本地文件或其餘服務器。這種方案的主要問題是須要針對代碼使用的各類庫進行定製插件,初期成本高;同時有部分的代碼入侵,須要保證入庫代碼正確。jquery

  • 攔截至數據文件:
    最典型的是Mock.js。這種方式實現了自由編寫數據,靈活性比較大,並且mock的數據文件能夠同步至倉庫中,下次開發時。缺點是一樣非網絡請求,真實性不足。webpack

  • 攔截並改變請求:
    這種方式之因此出現是由於服務器的URL和本機的URL規則不一樣,須要按照規則進行轉換。這種方式與真實狀況比較接近,同時產生了跨域,須要服務端提供對應的header。ios

3. 爲全部接口統一添加前綴

這種方式在公用文件中直接添加接口前綴,依賴於特定的庫功能(或者達到相同效果的代碼結構)。同以前的攔截並改變請求相似,但更爲簡單一些,只改前綴就能夠了,一樣有代碼入侵的問題。nginx

4. 使用其餘工具

這種方式分爲兩種:使用本地或軟件數據和代理轉發git

  • 使用本地或軟件數據:
    最經常使用的如:fiddler, charles, whistle等,能夠將請求返回指定內容。主要問題是配置比較繁瑣,全部操做都在本機,同步困難。

  • 代理轉發:
    這種方式和真實環境極爲接近,畢竟純靜態的文件,在服務端也是須要進行代理轉發的。可以使用的工具就比較多了,使用支持代理轉發的開發工具,或者使用上面提到的工具,一樣可以將數據轉發出去。這種方式最大的優勢是:無跨域、能發出真實請求、與業務代碼徹底隔離。

方案對比

對比以上幾種方案,最優的選用代理轉發方式,其次是代碼攔截方式。攔截至數據文件有個優點就是能夠將mock數據和倉庫同步,但在不一樣分支開發時Mock數據可能會衝突。代理轉發和攔截至服務器使用最方便,但它須要mockServer。只視開發狀況而定。

一些mock用工具

mock的實現很是多,基本上每套完善的前端開發工具都是自帶mock的機制。近幾年隨着nodejs的流行,前端能夠很是方便的實現本身的mockServer,因此想列舉出全部的仍是很困難的,這裏介紹一些知名字較高的工具。

1. swagger

  • 地址:[https://swagger.io/]
  • 介紹: 提到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結構數據,配合相應的工具來實現相似的效果。

2. Mock.js

  • 地址:https://github.com/nuysoft/Mock/tree/refactoring
  • 介紹:THX團隊出品,本地文件編寫mock數據規則,適用於代碼庫攔截,以前較爲流行的一個方案,不少工具都集成了Mockjs語法,目前倉庫已經再也不更新。

3. rap2

  • 地址:https://github.com/thx/rap2-delos
  • 介紹:同THX團隊出品,是rap0.x的升級版本,使用了nodejs和關係數據庫開發,兼容mock.js語法。界面比較簡潔,交互友好,支持界面式編輯API。但URL設計與原URL不一樣,須要使用代碼庫攔截方式。

4. apiary

  • 地址:https://app.apiary.io/
  • 介紹:這款在國外用的比較多一些,功能也是比較強大:

    Apiary.io平臺具備協同設計、即時API模擬、快速生成源碼、自動測試和代碼調試的開源設計工具,最重要的是能夠在線模擬測試,由於該平臺具有模擬服務器測試服務,能夠把設計好的程序在線測試、驗證。

5. easy-mock

  • 地址:https://easy-mock.com/
  • 介紹:搜車出品,rest api模擬,基於mockjs語法,可以從swagger生成簡單數據。

6. yapi

  • 地址:http://yapi.qunar.com/getfamiliar.html
  • 介紹:這是去哪團隊作的,使用了nodejs+mongodb方式開發,主要特性:

    • 基於 Json5 和 Mockjs 定義接口返回數據的結構和文檔,效率提高多倍
    • 扁平化權限設計,即保證了大型企業級項目的管理,又保證了易用性
    • 相似 postman 的接口調試
    • 自動化測試, 支持對 Response 斷言
    • MockServer 除支持普通的隨機 mock 外,還增長了 Mock 指望功能,根據設置的請求過濾規則,返回指望數據
    • 支持 postman, har, swagger 數據導入
    • 免費開源,內網部署,信息不再怕泄露了

rap2和yapi的一些對比

接入mockServer

有了各類極爲方便使用的mockServer,想要接入就很簡單了。mockServer的通常使用規則:

  • URL相同,直接代理轉發便可
  • URL後半部分相同,直接加上URL前綴便可
  • URL規則不一樣,或須要身份認證,須要攔截轉發

攔截式

攔截式針對的是使用一些封裝過的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標籤便可(部分攔截可能須要引入多個標籤)。

修改全局URL式

這種狀況適合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數據再真實,也沒法實現和後端接口同樣的邏輯,部分邏輯檢查或業務的問題只能聯調才能發現。
  • mock不能替代測試。mock自己是爲了加快開發速度,那些對於代碼質量要求比較高的項目,mock服務只能提供一些case。

總結

使用mock前提是先後端有一個明確的接口協議,利用合適的工具才能提升開發效率。強大的mock服務可使你對開發的代碼更爲自信,即便沒有後端,新手就能夠經過mock熟悉以前的業務界面,或者查看一些表現特殊的界面,最大程度減小對後端的依賴。

上面介紹的幾款mockServer有幾種都是使用nodejs開發的。和其餘語言開發的mock服務相比,json格式成爲書寫的主要格式,雖然用起來容易,但書寫上並不方便(json5格式在某種程度上加強了書寫體驗,但相比yaml等格式仍是有所不足)。同時業務狀況不一樣,針對性的選擇不一樣的平臺,推薦使用rap2和yapi,前者界面更爲簡潔,操做方便,後者功能更爲強大。若是有特殊的須要,能夠本身寫一個,順便練練手。

搭建一個屬於本身的server

參考

【你是如何構建 Web 前端 Mock Server 的? - 莫池宇的回答 - 知乎
https://www.zhihu.com/question/35436669/answer/235608128

相關文章
相關標籤/搜索