純手工打造前端后端分離項目中的mock-server

為了更好的分工合作,讓前端能在不依賴后端環境的情況下進行開發,其中一種手段就是為前端開發者提供一個web容器,這個本地環境就是 mock-server。

數據mock可以有兩種思路:

  • 在 client 端mock
  • 在 server 端mock

第一種方式攔截了請求的發出,直接返回 mock 的數據,而第二種方式請求則真實地發出,只是在 server 端進行 route 攔截。然而身為一名有“尊嚴”的前端怎么能去求后端呢?所以我們毫不猶豫的選擇第一種方式。

目前很多前端 mock 數據的方案的基本流程都是使用 node.js 來模擬 http 請求,配置 router 返回 mock 數據。

讓我們設想一下一個比較好的 mock-server 該有的能力:

  • 與線上環境一致的接口地址,每次構建前端代碼時不需要修改調用接口的代碼
  • 所改即所得,具有熱更新的能力,每次增加/修改 mock 接口時不需要重啟 mock 服務,更不用重啟前端構建服務
  • 能配合 Webpack
  • mock 數據可以由工具生成不需要自己手動寫
  • 能模擬 POST、GET 請求
  • 簡單(包括:文件結構簡單、編寫代碼簡單)

所以接下來給大家介紹一下我自己總結下來一套使用起來比較舒服的 mock-server 解決方案,其中也用到了許多工具和框架,在整個搭建過程中自己同時也學習了很多。

大致的主要思路:以 json-server 作為 mock 服務器, mock.js 生成 mock 數據,利用 gulp + nodemon + browser-sync 監聽 mock 文件的改動重啟 node 服務,刷新瀏覽器,以此達到一種相對完美的 mock-server 要求。

json-server搭配mock.js

這里以 Webpack 的前端工程為例:

npm install json-server mockjs --save

在項目根目錄新建 mock 文件夾,新建 mock/db.js 作為 mock 數據源,mock/server.js 作為 mock 服務,mock/routes.js 重寫路由表。

// db.js
var Mock = require('mockjs');

module.exports = {
  getComment: Mock.mock({
    "error": 0,
    "message": "success",
    "result|40": [{
      "author": "@name",
      "comment": "@cparagraph",
      "date": "@datetime"
    }]
  }),
  addComment: Mock.mock({
    "error": 0,
    "message": "success",
    "result": []
  })
};

這里我們利用 mock.js 生成 mock 數據,可以盡可能的還原真實數據,還可以減少數據構造的復雜度。

// routes.js
module.exports = {
  "/comment/get.action": "/getComment",
  "/comment/add.action": "/addComment"
}

我們可以通過路由表的配置實現復雜的路由配置,詳細配置規則

// server.js
const jsonServer = require('json-server')
const db = require('./db.js')
const routes = require('./routes.js')
const port = 3000;

const server = jsonServer.create()
const router = jsonServer.router(db)
const middlewares = jsonServer.defaults()
const rewriter = jsonServer.rewriter(routes)

server.use(middlewares)
// 將 POST 請求轉為 GET
server.use((request, res, next) => {
  request.method = 'GET';
  next();
})

server.use(rewriter) // 注意:rewriter 的設置一定要在 router 設置之前
server.use(router)

server.listen(port, () => {
  console.log('open mock server at localhost:' + port)
})

現在打開 terminal 輸入命令

$ node mock/server.js

打開 http://localhost:3000/comment/get.action 即可查看到我們想要的數據:

是不是這樣就算搭建完了我們的 mock-server ?不,并沒有。我們可以嘗試修改一下 db.js 的文件內容,刷新瀏覽器發現 mock 數據并沒有像我們想象的那樣修改。那也就是說每次當我們需要添加/修改 mock 數據使都需要重啟一次 mock 服務。What ???

除此之外我們還需要進行端口代理,以至于不與 Webpack 的構建端口產生跨域。

端口代理

通過 Webpack 配置 proxy 代理:

module.exports = {
  ...
  devServer: {  
    //其實很簡單的,只要配置這個參數就可以了  
    proxy: {  
      '/api/': {  
        target: 'http://localhost:3000',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  } 
}

接著在代碼里進行 ajax 請求就可以寫成,這里以 axios 為例子:

function getComments () {
  axios.get('api/comment/get.action', {}).then((res) => {
    console.log(res.data)
  })
}

文件改動自動刷新

我們希望更改 mock 文件能和 webpack 熱更新一樣,所改即所得。這里我使用了 nodemon,利用 gulp 建立自動執行的任務。

npm install gulp gulp-nodemon browser-sync --save

gulpfile.js 的代碼如下:

const path = require('path');
const gulp = require('gulp');
const nodemon = require('gulp-nodemon');
const browserSync = require('browser-sync').create();
const server = path.resolve(__dirname, 'mock');

// browser-sync配置,配置里啟動nodemon任務
gulp.task('browser-sync', ['nodemon'], function() {
  browserSync.init(null, {
    proxy: "http://localhost:8080", // 這里的端口和webpack的端口一致
    port: 8081
  });
});

// browser-sync 監聽文件
gulp.task('mock', ['browser-sync'], function() {
  gulp.watch(['./mock/db.js', './mock/**'], ['bs-delay']);
});

// 延時刷新
gulp.task('bs-delay', function() {
  setTimeout(function() {
    browserSync.reload();
  }, 1000);
});

// 服務器重啟
gulp.task('nodemon', function(cb) {
  // 設個變量來防止重復重啟
  var started = false;
  var stream = nodemon({
    script: './mock/server.js',
    // 監聽文件的后綴
    ext: "js",
    env: {
      'NODE_ENV': 'development'
    },
    // 監聽的路徑
    watch: [
      server
    ]
  });
  stream.on('start', function() {
    if (!started) {
      cb();
      started = true;
    }
  }).on('crash', function() {
    console.error('application has crashed!\n')
    stream.emit('restart', 10)
  })
});

這樣以后我們在構建我們 Webpack 工程時只需要先執行

$ npm run dev

之后新建 terminal 執行

$ gulp mock

就可以搭建一個隨改隨變的 mock-server 環境,再也不用看后臺的臉色啦~

如果有任何問題歡迎留言

個人的 vue-starter-kit 項目也采用了這種 mock 方案,如果有需要也可以參考,歡迎 star

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

推薦閱讀更多精彩內容