vue-cli3 本地mock數據實現

緣由

起初使用mockjs2進行本地的mock開發,過程當中發現控制檯中network看不到請求,這再開發中至關不舒服,根本看不到請求接口的參數,對於查詢等操做很是不方便,因而開始對項目的mock方式進行了修改,經過vue-cli3的express服務建立。vue

目錄結構

testdata文件夾中,目錄對應接口目錄進行建立vue-cli

├── mock
│   ├── testdata
│   │ mock-server.js
│   │ utils.js
├── config
├── public 
├── src
...
├── static
.env.mock
package.json
...

啓動

我是經過環境變量和模式的方式啓動本地mock環境 .env.mock 和 .env.development 進行區分環境,package.json中添加啓動mock的命令:express

"scripts": {
    "local": "vue-cli-service serve --mode mock",
    "serve": "vue-cli-service serve",
    ...
},

.env.mockjson

NODE_ENV=mock

改造vue.config.js

首先作的就是先經過devServer的功能進行修改api

devServer: {
   before: require('./mock/mock-server.js'),
   port: 8080
},

在before的時候加載mock-server.js 文件app

const fs = require('fs-extra')
const path = require('path')
const JSON5 = require('json5')
const Mock = require('mockjs2')
const { delay } = require('./utils.js')

// 接口前綴
const devServerMockUrlMatch = /^\/api\//

async function getMockData(dataFilePath, method) {
    const fileJsonPath = `${dataFilePath}.json`
    const fileMockjsPath = `${dataFilePath}.mockjs.json`
    const fileRestFulPath = `${dataFilePath}$${method.toLowerCase()}.json`
    const fileRestFulMockjsPath = `${dataFilePath}$${method.toLowerCase()}.mockjs.json`
    const fileExist = await fs.pathExists(dataFilePath)
    const fileJsonExist = await fs.pathExists(fileJsonPath)
    const fileMockjsExist = await fs.pathExists(fileMockjsPath)
    const fileRestFulExist = await fs.pathExists(fileRestFulPath)
    const fileRestFulMockjsExist = await fs.pathExists(fileRestFulMockjsPath)

    // 先尋找 RESTFul .mockjs.json 文件
    if (fileRestFulMockjsExist) {
        return fs.readFile(fileRestFulMockjsPath, 'utf8').then(json => JSON.stringify(Mock.mock(JSON5.parse(json))))
    }

    // 再尋找 RESTFul .json 數據文件
    if (fileRestFulExist) {
        return fs.readFile(fileRestFulPath, 'utf8')
    }

    // 再尋找 .mockjs.json 後綴 mock 數據文件
    if (fileMockjsExist) {
        return fs.readFile(fileMockjsPath, 'utf8').then(json => JSON.stringify(Mock.mock(JSON5.parse(json))))
    }

    // 再尋找 .json 後綴 mock 數據文件
    if (fileJsonExist) {
        return fs.readFile(fileJsonPath, 'utf8')
    }

    // 再尋找無後綴 mock 數據文件
    if (fileExist) {
        return fs.readFile(dataFilePath, 'utf8')
    }

    console.error('------- ERROR ------')
    console.error('嘗試瞭如下可能的 mock 數據文件,仍沒有找到對應的數據')
    console.error(`1. ${fileRestFulPath}`)
    console.error(`2. ${fileRestFulMockjsPath}`)
    console.error(`3. ${fileJsonPath}`)
    console.error(`4. ${fileMockjsExist}`)
    console.error(`5. ${dataFilePath}`)
    return Promise.reject(new Error('沒有找到對應mock數據文件'))
}

module.exports = app => {
    // 只有環境變量是mock的狀況纔會進入
    if (process.env.NODE_ENV === 'mock') {
        console.info('開啓本地mock數據調試模式...')
        app.all(devServerMockUrlMatch, async (req, res) => {
            const { method, originalUrl } = req
            console.info(`本地數據請求:[${method}] ${originalUrl}`)
            try {
                // 響應延遲500ms,模擬請求
                await delay(500)
                const dataFilePath = originalUrl
                    .replace(devServerMockUrlMatch, `${path.join(process.cwd(), 'mock/testdata')}$&`)
                    .replace(/\?.*$/, '')
                let data = await getMockData(dataFilePath, method)

                res.append('Access-Control-Allow-Origin', true)
                try {
                    data = JSON5.parse(data)
                } catch (e) {
                    const errMsg = `local mock json data parse error (本地測試數據JSON解析錯誤): ${dataFilePath}`
                    throw new Error(`${errMsg}\n${e}`)
                }
                res.json(data)
            } catch (err) {
                console.error(err)
                res.status(500).send(err.stack)
            }
        })
    }
}

utils.jsasync

const chalk = require('chalk')

const delay = function(time) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve()
        }, time)
    })
}

const utils = {
    delay
}

module.exports = utils

process.on('unhandledRejection', reason => {
    console.log(chalk.red(reason))
    console.error(reason.stack)
    process.exit(1)
})

結束

啓動mock環境以後終於能夠開心的進行mock開發啦。我如今是直接獲取請求中的地址,而後從本地文件中進行查找,因此testdata中的目錄可能會由於請求地址比較深而建立多層文件夾,可是有利有弊吧,對於我本身而言,若是經過接口看mock數據只須要按照文件夾進行查找就好,感受理解起來更方便。若是還有其餘更好的方式請多多指教~~測試

文筆有限,多多指教。ui

相關文章
相關標籤/搜索