在webpack-dev-server中添加mock中间件实现前端模拟数据功能

·  阅读 1614

利用webpack-dev-server的before方法,拦截请求,将请求的路径映射到本地mock目录中的js文件中的数据。

mock中间件实现的功能

  • 请求的路径和mock目录的路径相对应,找不到则返回404
  • 可直接返回响应数据
  • 返回一个方法,参数为请求的常用参数,返回为响应数据,可实现处理请求返回不同响应结果。

项目目录结构

├─package.json
├─src
|  ├─index.css
|  ├─index.html
|  ├─index.js
├─dev
|  ├─mock
|  |  ├─fun.js
|  |  └test.js
├─build
|   ├─fs-async.js
|   ├─mock.js
|   └─webpack.config.js
复制代码

运行命令

  • webpack-dev-server --config build/webpack.config.js
  • 或者在package.jsonscript中设置
    {
        "scripts": {
            "dev": "webpack-dev-server --config build/webpack.config.js"
        }
    }
    复制代码
    然后 npm run dev

webpack-dev-server配置

const mock = require('./mock.js');
module.exports = {
	mode: 'development',
	// 开发服务器配置
	devServer: {
     	// 指向打包目录
        contentBase: path.resolve(__dirname, '../dist'),
        port: 8080, // 服务端口号
        progress: true, // 打包进度
        open: true, // 是否打开浏览器
        compress: false, //是否压缩
        before: (app) => {
            mock(app);
		}
    },
    // 其他配置。。。
}
复制代码

实现获取mock数据的express中间件

mock.js

const path = require('path');
const fs = require('fs');
/**
 * 读取本地mock数据
 * @param {*} req 
 */
function readMockData(req) {
    const {url, pathname, param, method} = req;
    return new Promise((resolve, reject) => {
        const filepath = path.resolve(__dirname, '../dev/mock' + pathname + '.js');
        const fileExist = fs.existsSync(filepath);
        if (!fileExist) {
            const msg = `'${url}': mock data is not exist!`;
            reject({
                statusCode: 404,
                body: null,
                message: msg
            });
        } else {
            try {
                delete require.cache[require.resolve(filepath)];
                const response = require(filepath);
                if (typeof response === 'function') {
                    const responseFun = response(req);
                    resolve(responseFun);
                    return;
                }
                resolve(response);
            } catch (err) {
                console.log('readMockError:', err);
                const msg = `'${url}': parse mock file error!`;
                reject({
                    statusCode: 500,
                    body: null,
                    message: msg
                });
            }
        }
    });
}
/**
 * express中间件,实现ajax mock数据功能
 * @param {*} app 
 */
module.exports = function mock(app) {
    app.all('*', function (req, res, next) {
        const method = req.method.toLocaleUpperCase();
        const param = method === 'GET' ? req.query : req.body;
        // 请求日志打印
        console.log(req.method, req.url, param, Date.now());
        // 只处理ajax请求
        if (req.headers['x-requested-with'] === 'XMLHttpRequest') {
            readMockData({
                url: req.url,
                pathname: req.path,
                param,
                method
            }).then(response => {
                res.status(response.statusCode || 200);
                res.setHeader('Content-Type', 'application/json');
                res.end(JSON.stringify(response.body));
            }).catch(err => {
                res.status(err.statusCode || 404);
                res.end();
            });
        } else {
            next();
        }
    });
}
复制代码

mock文件数据内容

  • test.js
module.exports = {
    statusCode: 200,
    body: {
        code: 0,
        message: 'ok',
        data: {
            text: 'aabbcc'
        }
    }
};
复制代码
  • fun.js
// 输出一个函数,可以根据请求的参数做对应的响应
module.exports = function (req) {
    const param = req.param;
    const method = req.method;
    return {
        statusCode: 200,
        body: {
            code: 0,
            message: 'ok',
            data: {
                text: 'abcd',
                param,
                method
            }
        }
    }
};

复制代码
分类:
前端
标签: