起因.
- 網上找了很多mockjs(是mockjs不是其他的mock插件)環境的配置, 基本全是錯的.
- 生產環境不需要mock, 開發環境有時需要mock有時不需要mock.
- 可能這個功能點太小了, 導致大家都不在乎.
- 但是越小的點越有趣味.
一. 要達到的效果
- 不可以手動注釋掉import './mock'這段話, 因為只要是人為操作就會存在失誤的可能性.
- 用es6的模塊規則書寫, 而不用common
- 區分 yarn mock 與 yarn xxx
- 寫着爽, 可擴展, 核心代碼不用動
二. 想到的各種方法與坑
方法一. 我們公司之前使用的是"express"自己起了一個服務, 然后讀取文件夾名為path, 內容當然就是內容了, 這樣做也沒問題, 但是畢竟不是專業的處理方式, 比如同一個path既是get地址又是post地址, 那這個區分起來就需要改動代碼了, 還有就是在模擬數據的隨機性上幾乎沒有, 比如mockjs可以模擬 1-12位的數字返回, 而當前這種方式只能"寫死", 是在不是寫個隨機函數然后每次都調用函數, 這樣越做越大沒實際意義, 還不如采用成熟的方案.
方法二:
mockjs
下載: yarn add mockjs -D 只是開發使用, 誰會把這個放到生產??
調用: import Mock from 'mockjs'
具體怎么配置就不說了, 簡單的過分, 一會可以說下工程化
方法三:
封裝好的axios請求外面, 再封裝一層mock層, 這個就想想吧,太邪門歪道了.
廣州設計公司https://www.houdianzi.com 我的007辦公資源網站https://www.wode007.com
三. 知識點與坑點(好玩的來了)
網上都說利用cross-env來區分環境變量, 但是這里有個大坑你知道么???
我選擇的是"cross-env": "^6.0.3"
在package.json里面配置 "mock": "cross-env MOCK=true vue-cli-service serve",
本以為大功告成了, 在main.js里面下面代碼完全不執行
if(process.env.MOCK === 'true'){...}
坑點1:
cross-env屬於node環境, 這個值在web代碼里面是取不到的, 這個值可以在vue.config.js里面import我們的mockjs, 但是會報錯, 不可以使用es6的引入方式, 需要commonjs的方式里面拿到, 那我們轉移戰場, 在 vue.config.js里面import我們的mockjs, 但是會報錯, 不可以使用es6的引入方式, 需要commonjs的方式require進來
(想要在客戶端側代碼中使用環境變量: process.env.VUE_APP_xxx, 但是有這個變量 import語法也不支持按需決定引入與否)
坑點2:
用require的方式引入mockjs, 那么意味着mock文件的工程化不能用es6的寫法去做了, 真的忍不了啊
坑點3:
require的方式引入會報Mock.setup找不到的錯誤, 這個估計是mockjs本身就沒想讓用戶這樣引用.
坑點4:
用require的方式引入了,也執行了, 但是無效, 因為mockjs的實現方式不是在外界起一個服務然后監聽一個工程的請求.
想其他辦法吧
首先mock既然需要import的方式在main.js里面引入, 那我還就這樣使用了, 那我們其實可以在文件級別來解決這個問題, 問題被提煉出來了在main.js文件里面yarn mock的時候加上'"import './mock'"', yarn xxx 去掉"import './mock'", 這很清晰明了了,真的很暴力.
涉及到修改文件node出場
先來規范一個站位符吧, 畢竟需要區分是否插入, 以及插在哪里, 這樣后來的同學也能順藤摸瓜找到整體的邏輯
大家一定要注意, 代碼一定要是連續的, 不可以出現憑空出現某些邏輯這種寫法, 比如vue的mixins方法, 這個會導致項目很難交接, 無法定位問題等等壞處
1.// mock : 短小精悍,缺點明顯, 不定誰就該刪除了.
2./** mock(不要刪除) **/: 比第一個更有戲劇性了.
3.不寫占位符, 直接操作, 這樣就是不符合代碼邏輯連貫性原則, 新同學可能都不知道你的操作怎么實現的, 不建議完全無感的操作, 雖然留一個占位符看着挺low, 但是方便追溯.
node判斷文件內容(簡單的替換)
添加邏輯
const path = require('path'); const fs=require("fs"); let main = fs.readFileSync( path.resolve(__dirname, '../src/main.js'),'utf-8'); main = main.replace('/** mock(不要刪除) **/', "import '../mock'"); fs.writeFile(path.resolve(__dirname, '../src/main.js'), main, 'utf8', (err) => { if (err) throw err; console.log('成功引入mock數據'); });
刪除邏輯
const path = require('path'); const fs=require("fs"); let main = fs.readFileSync(path.resolve(__dirname, '../src/main.js'),'utf-8'); main = main.replace( "import '../mock'", '/** mock(不要刪除) **/'); fs.writeFile(path.resolve(__dirname, '../src/main.js'), main, 'utf8', (err) => { if (err) throw err; console.log('去掉mock數據'); });
兩個腳本寫完開始引入把(下面代碼的錯誤你看出來了么)
"scripts": { "mock":"node ./mock/add.js vue-cli-service serve", "serve": "node ./mock/delete.js vue-cli-service serve", "build": "node ./mock/delete.js vue-cli-service build" },
運行起來你就會發現vue-cli-service serve不執行, 這是因為這條語句需要區分一下
很多同學這里進坑了, 下面的寫法有時也是有bug的
"scripts": { "mock":"node ./mock/add.js && vue-cli-service serve", },
正確的寫法如下 &&需要緊貼 node語句, 否則可能會有莫名其妙的bug出現, 也算是小知識.
"scripts": { "mock":"node ./mock/add.js&& vue-cli-service serve", },
我也想過, 每行都寫node ./src/mock/add.js這種代碼 , 不如把每個命令都放在node里面就好了, 直接npx之類的去執行就可以了, 但是我不這樣做還是因為上面的原因, 這樣寫會打亂其他同學的編寫習慣, 讓別人蒙b但是效益不大, 那么就不要去做了.
四. 工程化結構
本着工程化的原則,肯定是要單獨建立一個mock文件夾, 這個不要放在src里面了, 要與src平級, 里面的index文件負責導出所有的接口, 因為考慮到大的需求可能會新增幾十個接口, 所以我還是建議再建立一個本次版本的mock接口的文件夾, 這樣也方便集體刪除不留后遺症, 如果某些接口需要mock很復雜的數據形式, 那還是要單獨建立一個文件來存放他的邏輯內容, 雖然mock的時候不寫method默認就是get, 我還是建議吧get 寫上, 這樣更直觀