原文地址:http://marxjiao.com/2017/06/02/mock-webpack-plugin/
對于前后端開發(fā)的項(xiàng)目,大部分的情況是先約定好接口格式怨咪,前端使用本地mock數(shù)據(jù)進(jìn)行開發(fā)谨胞,開發(fā)后使用后端接口聯(lián)調(diào)帮辟。webpack-dev-server提供了proxy配置肴楷,我們可以在開發(fā)中將接口代理到本地服務(wù)鸟妙。mock數(shù)據(jù)使用json文件能最方便的進(jìn)行開發(fā)京痢,然而在webpack-dev-server 1.6以后的版本并不支持將接口代理到j(luò)son文件奶甘。webpack-dev-server的proxy使用的是http-proxy-middleware,這個issue說明了原因祭椰。
所以在開發(fā)過程中我們需要搭建服務(wù)器臭家,來將接口指向json文件。我開發(fā)了一個webpack插件方淤,是起一個express服務(wù)來serve這些接口钉赁,并根據(jù)配置指向相應(yīng)的json文件。
本文介紹插件開發(fā)細(xì)節(jié)携茂,算是開發(fā)文檔你踩。如果只是想使用插件的話可以查看readme。
選型
webpack dev server使用的express啟動本地服務(wù)器邑蒋,所以這里的mock server也選用express開發(fā)姓蜂。
設(shè)計(jì)思路
- webpack初始化插件時,將需要的配置信息傳遞給插件
- 插件啟動express
- 使用express中間件處理請求医吊,如果請求的接口匹配配置信息钱慢,就讀取對應(yīng)的json文件,將內(nèi)容返回
開發(fā)
先寫一個用來啟動express服務(wù)的函數(shù)卿堂。調(diào)用函數(shù)時啟動一個express server束莫。
var express = require('express');
// 這里是處理請求的中間件
var returnData = require('./returnData.js');
module.exports = function({config, port = 3000}) {
// 判斷配置信息存在
if (config) {
const mockPort = port || 3000;
// 新建express應(yīng)用
var app = express();
// 使用中間件將配置信息放在請求對象里懒棉,方便后邊的中間件使用
app.use((req, res, next) => {
req.config = config;
next();
})
// 用中間件處理所有請求
app.use(returnData);
// 啟動server
var server = app.listen(mockPort, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Mock server listening at http://%s:%s', host, port);
});
}
else {
console.log('No Config File!')
}
}
處理請求的中間件returnData.js。從請求中讀取配置信息览绿,如果請求的接口在配置中策严,則讀取對應(yīng)的文件,如果不在饿敲,返回提示信息妻导。這里使用promise封裝了fs.readFile方便使用async/await調(diào)用。
const fs = require('fs');
module.exports = async function(req, res, next) {
const config = req.config;
// 判斷請求的接口在配置中
if (config[req.path]) {
// 讀取對應(yīng)的json文件
const data = await fsRead(config[req.path].path);
// 返回json文件
res.send(JSON.parse(data));
}else {
// 如果接口沒在配置中怀各,返回錯誤信息
res.send({errno: -1, msg: 'No such proxy: ' + req.path});
}
next();
}
// 使用promise封裝fs.readFile倔韭,方便使用async/await
function fsRead(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, (err, data) => {
if (err) {
if (err.syscall === 'open') {
console.log('Open "' + err.path +'" fail!')
}
reject(err);
}
resolve(data.toString())
})
})
}
server相關(guān)的代碼就寫好了,下面只需要寫一個webpack插件瓢对,再插件調(diào)用時啟動express就好了寿酌。
const server = require('./server.js');
function MockWebpackPlugin({config, port = 3000}) {
// 將config和port放在屬性里,方便apply方法調(diào)用
this.config = config;
this.port = port;
}
MockWebpackPlugin.prototype.apply = function (compiler) {
// 調(diào)用啟動express的函數(shù)
server({config: this.config, port: this.port});
// 注冊一個webpack插件
compiler.plugin("emit", (compilation, callback) => {
callback();
});
}
?
到這里插件就開發(fā)完了硕蛹。?如何使用請看這里
項(xiàng)目源碼:https://github.com/MarxJiao/mock-webpack-plugin