點燈坊

失くすものさえない今が強くなるチャンスよ

使用 MSW 建立 Mock API (Vue CLI)

Sam Xiao's Avatar 2021-05-17

建立假 API 不難,但若要在 API Function 不修改前提下建立 Mock API,等 API 建立好後無痛接上就有挑戰性,Mock Service Worker 讓我們可以在不修改 Codebase 前提下無痛切換 Mock API。

Version

Vue 2.6.11
MSW 0.28.2

Vue Project

$ vue create vue2-msw

使用 Vue CLI 建立 Vue。

API Function

api/getBook.js

import axios from 'axios'

export default id => axios.get(`/book/${id}`)

如同往常一樣呼叫 API,並沒有特意回傳 JSON。

Component

App.vue

<template>
  <div>
    <div>
      <button @click='onClick'>Get Book</button>
    </div>
    <div>
      {{ title }}
    </div>
  </div>
</template>

<script>
import getBook from '@/api/getBook'

let onClick = function() {
  getBook(1)
    .then(x => x.data)
    .then(x => this.title = x.title)
    .catch(console.error)
}

export default {
  name: 'App',
  data: () => ({
    title: ''
  }),
  methods: {
    onClick
  }
}
</script>

15 行

let onClick = function() {
  getBook(1)
    .then(x => x.data)
    .then(x => this.title = x.title)
    .catch(console.error)
}

如同往常在 Vue 呼叫 API function。

cli000

毫無意外執行後會 404 error,因為 API 根本不存在。

MSW

$ yarn add --dev msw

使用 Yarn 安裝 Mock Service Worker。

Mock API

mock/getBook.js

import { rest } from 'msw'

export default rest.get('/book/1', (req, res, ctx) => {
  return res(
    ctx.status(200),
    ctx.json({
      'title': 'FP in JavaScript',
    })
  )
})
  • 建立 mock 目錄,與 API function 名稱一樣也叫 getBook.js
  • 使用 MSW 的 rest.get() 建立 RESTFul GET API

mock/index.js

import { setupWorker } from 'msw'
import getBook from './getBook'

export default setupWorker(getBook)

mock 目錄下建立 index.js,MSW 將 Mock API 交給 service worker 處理。

Main

main.js

import Vue from 'vue'
import worker from './mock'
import App from './App.vue'

Vue.config.productionTip = false

if (process.env.NODE_ENV === 'mock')
  worker.start()

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

main.js 引用 service worker,當 NODE_ENVmock 時啟動 MSW。

NPM Script

package.json

{
  "name": "vue2-msw",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "mock": "NODE_ENV=mock vue-cli-service serve"
  },
  "dependencies": {
    "axios": "^0.21.1",
    "core-js": "^3.6.5",
    "vue": "^2.6.11"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "msw": "^0.28.2",
    "vue-template-compiler": "^2.6.11"
  },
  "msw": {
    "workerDirectory": "public"
  }
}

第 9 行

"mock": "NODE_ENV=mock vue-cli-service serve"

NODE_ENV=mock 啟動 Vite。

Init File

$ npx msw init public/

public 目錄下建立 service worker 啟動檔。

Run MSW

$ yarn mock

啟動 Vite 與 MSW。

當執行 yarn serve 時將如往常直接呼叫 API,只有 yarn mock 會啟動 MSW 攔截 API

cli001

Console 顯示 Mocking enabled 表示 MSW 已經成功啟動,順利從 API 取得資料並顯示。

Conclusion

  • MSW 讓我們可以在不用修改 codebase 前提下,動態切換 Mock API 與真實 API

Reference

Andy Li, Mock Service Worker: API Mocking for Vue.js Developing & Testing