webpack+mock Server 与后端并行开发


外圆内方 2019-2-26 Webpack Mock

使用 mock 开发的优点

  1. 不依赖后端进度。只要根据需求与后端列出接口,约定好接口内容就能开发。
  2. 职责分明。随着前端的发展,业务逻辑部分也开始放在客户端。这就不可避免的可能会与后端同学产生冲突,在约定接口内容后有利于提前化解这样的问题,避免撕 X。提高工作效率。
  3. 独立运行。即使没有后台服务也能打开项目。避免以后想看项目,启动都是报错的问题。

使用 Express 来实现 Mock Server

// 引入node的path
var path = require("path")
// 引入node的文件模块
var fs = require("fs")
// 引入mockJs
var mock = require("mockjs")
// 构建express应用
var app = require("express")()
/* process.argv返回一个数组,其中包含当启动 Node.js 进程时传入的命令行参数。
    第一个元素是 node.exe 执行文件的路径
    第二个元素将是正在执行的 JavaScript 文件的路径(这个是配置在npm script 中的mockServer.js的路径)
    第三个是npm script 里面配置的mockServer的端口号
*/
var port = process.argv[2] || 8000

// 监听启动端口
app.listen(port, function() {
	console.info("Mock server is listening at " + port)
})
// webpackServer是否开启代理
const prefix = process.env.NODE_ENV != "production" ? "/api" : ""

// 获取同一文件夹下的api.json
var apiPath = path.join(__dirname, "./api.json")

// 读取api.json里面的接口内容
var api = {}
function getApis() {
	fs.readFile(apiPath, "utf-8", function(_, content) {
		api = JSON.parse(content)
	})
}

// 监听api.json变化
fs.watchFile(apiPath, function(curr) {
	getApis()
})
getApis()

// 支持callback
app.set("jsonp callback name", "callback")

// 使用中间件对获取的api.json内容进行处理返回
app.use(function(req, res) {
	var data
	var delay = 0
	for (var group in api) {
		if (
			api[group].find(function(reqData) {
				if (reqData.regexp) {
					if (!new RegExp(reqData.url).test(req.originalUrl)) {
						return false
					}
				} else if (req.originalUrl !== prefix + reqData.url) {
					return false
				}
				var apiRes = reqData.res
				data = reqData.mock !== false ? mock.mock(apiRes) : apiRes
				delay = reqData.delay || 0
				return true
			}) !== undefined
		) {
			break
		}
	}
	// CORS 跨域
	res.set("Access-Control-Allow-Origin", "*")
	res.set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS")
	res.set(
		"Access-Control-Allow-Headers",
		"Origin, X-Requested-With, Content-Type, Accept, Authorization"
	)
	// 返回处理过的数据
	data !== undefined
		? setTimeout(() => res.jsonp(data), delay)
		: res.sendStatus(404)
})

在 api.json 写入 mock:

{
	"登录模块": [
		{
			"url": "/portal/login",
			"desc": "用户登入",
			"mock": true,
			"res": {
				"code": 0,
				"msg": "success",
				"data": {
					"uname": "@cword(5,8)",
					"uid": 9
				}
			}
		},
		{
			"url": "/portal/updatePwd",
			"desc": "修改密码",
			"mock": true,
			"res": {
				"code": 0,
				"msg": "success",
				"data": {
					"msg": "修改成功"
				}
			}
		},
		{
			"url": "/portal/captchaImage",
			"desc": "验证码",
			"mock": true,
			"res": {
				"code": 0,
				"msg": "success",
				"data": {}
			}
		},
		{
			"url": "/portal/logout",
			"desc": "用户登出",
			"mock": true,
			"res": {
				"code": 0,
				"msg": "success",
				"data": {
					"msg": "登出成功"
				}
			}
		}
	]
}

最后在 npm script 上加上 mock server 启动命令:

{
	"scripts": {
		"start": "run-p start_dev mock",
		// ./src是项目路径
		"start_dev": "webpack-dev-server --inline --hot --host 0.0.0.0 --progress --port 3000 --colors --content-base ./src",
		// ./mock-server/server.js是mockServer路径 2618是端口号
		"mock": "node ./mock-server/server.js 2618"
	}
}

运行 npm run start