利用mock提高效率


利用mock提高效率

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

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

使用mock開發流程

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

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

常用的mock方式

1. 代碼層硬編碼

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

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

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

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

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

3. 為所有接口統一添加前綴

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

4. 使用其他工具

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

  • 使用本地或軟件數據:
    最常用的如: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

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

5. easy-mock

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

6. yapi

  • 基於 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】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM