Mirage JS——海市蜃樓

這期介紹一款比較別致的 mock 工具,mirage.js。說它別致,緣由是與競品有一點點區別:它是在客戶端啟動的一個 mock 服務,恰如“海市蜃樓”為遠程調度展現一幅 api 全景圖;實則是一種偽裝技術,在應用內存里攔截了所有請求。

Mirage JS

Mock API

上次有人在評論區問我,前端開發時怎樣避免啟動一堆后端服務。理想狀態下(理想狀態下,理想狀態下,重要的事情說三遍),有 mock 服務就行了——瀏覽器裝個代理插件,將 api 路由到 mock 服務上。Mock 服務器可以是后端倉庫里一個本地服務;也可以是線上的三方產品——比如國產開源的yapi——直接在線編輯。現代開發一般就是前后分離,前端開發時,后端小伙伴很可能還沒開工;mock api 就可以幫你擺脫這類窘境。當然,你習慣于前端 hard code,我無話可說……

OK,答疑結束,回到本期話題。Mirage JS 就是一款 API Mock 工具,比之常規 mock 服務,你不用裝代理插件了,因為它與前端代碼一起運行。接著看看怎么使用吧。

Guide

安裝就一筆帶過了——yarn add -D miragejs

然后在前端 src 目錄下寫一個 server.js 文件,用來定義所有的 mock api。代碼如下所示:

// server.js
import { Server } from "miragejs";

export function mockServer() {
  return new Server({
    routes() {
      this.namespace = "api";
      this.get('/todos', () => [ "Buy Onion" ]);
    }
  })
}

Mirage 代碼還是挺直白的:在routes方法里定義了一個 Get API——/api/todos——返回我們所需要的 mock 數組[ "Buy Onion" ]。一個最簡單的 mock 服務就完工了。我們以 vue 項目為例,在入口文件 main.js 里引入 server.js,并新建這個 mock 服務。

import Vue from "vue";
import { mockServer } from "./server";

mockServer();

new Vue({
  render: h => h(App)
}).$mount("#app");

和平日里一樣,用 webpack 啟動 vue 項目,該 mock 服務就跟隨整個前端項目啟動了,并且共享 webpack 熱加載。與傳統的本地 mock 服務比起來,你可以少打一行命令,減少了 50%的操作。至于前端組件,和往常一樣不需要做任何改變:

// Todos.vue
<template>
  <ul>
    <li v-for="todo in todos">
    {{ todo }}
    </li>
  </ul>
</template>

<script>
export default {
  async created() {
    const {data} = await axios.get("/api/todos");
    this.todos = data;
  }
}
</script>

看一下效果吧,頁面根據 mock api 顯示列表,并在修改 mock 數據后,自動熱加載更新。

Mock Todos

More

當然,Mirage 的功能不止如此,它順便集成了一套簡單的前端數據庫,實現了常規的增刪改查交互操作。

export function makeServer() {
  return new Server({
    seeds(server) {
      server.db.loadData({
        todos: [
          { text: "Buy Onion", isDone: false },
          { text: "Buy Garlic", isDone: false }
        ]
      });
    },

    routes() {
      this.namespace = "api";

      this.get("/todos", ({ db }) => {
        return db.todos;
      });

      this.patch("/todos/:id", (schema, request) => {
        let todo = JSON.parse(request.requestBody).data;
        return schema.db.todos.update(todo.id, todo);
      });

      this.post("/todos", (schema, request) => {
        let todo = JSON.parse(request.requestBody).data;
        return schema.db.todos.insert(todo);
      });

      this.delete("/todos/:id", (schema, request) => {
        return schema.db.todos.remove(request.params.id);
      });
    }
  });
}

大家可以看下面這個圖片,交互數據全部來自 Mirage 的 mock api:

CRUD

實現一套前端 DB 來維護各色 mock api,在實際開發中還是有一定難度的。只有配合極佳的前后端團隊才能做到:

  1. 前后端商討一份接口方案
  2. 各自回頭開發,開發階段全程啟動 mock 模式
  3. 前后端代碼合并
  4. 生產環境調試——唉,完美無缺!

現實工作中,前端很可能還是會依賴真實的生產數據開發,Mock API 大概率就沒人鳥了。不過,測試代碼倒是一直需要 Mock 數據。

Mock 測試

測試環境——尤其在一些沙箱環境里——調用其他服務的 api 一直很不方便的。比如上面的 Todos.vue 組件,加載前需要請求 api;在傳統的單元測試環境里,提供這個異步請求就很麻煩了。再看 Mirage,將一個偽裝的服務器一起放到沙箱里,就顯得異常好用:

import { makeServer } from "server.js";
import { mount } from '@vue/test-utils';
import Todos from '@/components/Todos.vue';

let server;

beforeEach(() => {
  server = makeServer({ environment: "test" });
});

it("Show todos from our server", () => {
  server.create("todo", { id: 1, text: "Buy Onion" })

  const wrapper = mount(Todos)
  await waitFor(wrapper, '[data-test-id="1"]')

  expect(wrapper.find('[data-test-id="1"]').text()).toBe("Buy Onion")
});

afterEach(() => {
  server.shutdown();
});

引入 Mirage 后,只要記得在測試前后開關 mock 服務即可,其他的代碼與常規的 vue 單元測試無異。還有,Mirage 支持增刪改查呀!不僅是 unit 測試,甚至可以用在本地的 e2e 測試上:

it("shows the todos from our server", () => {
  server.create("todo", { id: 1, text: "Buy Onion" })

  cy.visit("/");

  cy.get('[data-test-id="1"]')
    .should("eq", "Buy Onion");

  // CRUD operations...
});

其他的一些沙箱環境,如 storybook,有時也需要一些 api 交互,代理到 mock 服務器上還是耦合太高了。試試 Mirage, 你就能設計更簡潔的 stories 了。

小結

這期內容很少,介紹了一款國內還很小眾的 mock 工具——mirage.js。也沒啥好總結的,開發工具嘛就是用來提高生產效率的,讓你編碼舒服一點。當然,學習新工具也意味著增加新的認知成本,難點不在工具本身,而在于統一認識上。如果工作只是“撞鐘”或者本人已經“脫產”了,那這類工具自然也沒啥意義了。

相關

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380