0%

Mock服务器

动态构建:

webpack-dev-middleware:

将webpack构建输出的文件存储在内存中,正常情况下,webpack构建产出的文件会存储在output配置项指定的硬盘目录中,webpack-dev-middleware在此基础上建立一个文件映射机制,每当匹配到一个webpack构建产出文件的请求后便会将内存中与其对应的数据返回给发起请求的客户端,由于是内存的文件系统,没有好使的硬盘读写,数据更新很快,这也是webpack相较其他同类工具的优势之一

实际上,webpacl-dev-server是在Express和webpack-dev-middleware基础上进行的封装,但由于不具备Mock服务,我们需要自己封装本地开发服务器,注意:

  • 如何启用源文件的监听并触发动态编译
  • 如何令客户端可访问由HTML引用但是并未参与构建的本地静态文件,比如jQuery等第三方库,这类文件由独立的script标签引入,不参与webpack构建

webpack-dev-middleware配置项:

  • lazy:是否开启惰性模式
  • watchOptions-监听细节配置(默认)
  • aggregateTimeouy:指定webpack的执行频率,webpack将在此段时间内针对源代码所有修改都聚合到一次重新编译行为中
  • ignored:指定不参与监听的文件
  • poll:指定webpack监听无效时轮询检验文件的频率

实际开发中并非所有的静态文件都参与构建,一些常用第三方库通常用单独的script和link标签引入,此类文件不参与构建,不在webpack-dev-middleware的监听范围内,也就不能通过文件映射策略将其对应的请求映射到内存文件系统中,只能借助express内置的static中间件将这些文件作为静态内容开放给Http服务,

1
app.use('/libs',express.static(path.join(process.cwd(),'static')))

第一个参数/libs是客户端请求静态资源的路径,express.static的参数时本地存放静态资源的绝对路径,上述代码将/libs路径的http请求映射到本地项目的static目录

创建一个本地开发服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const express=require('express')
const webpack=require('webpack')
const path=require('path')
const webpackdevmiddleware=require('webpack-dev-middleware')
const app=express()
const compiler=webpack({
//webpack配置
})
//配置中间件
app.use('/libs',express.static(path.join(process.cwd(),'static')))
.use(webpackdevmiddleware(compiler,{
lazy:false,
watchOprtions:{
aggregateTimeout:300,
ignored:/node_modules/,
poll:false
}
}))
app.listen(8888,err=>{
if(err){
throw new Error(err)
}
})

Mock

1 假数据

2 客户端Mock

Mock进化的第二种形态就是以Mock.js为代表的客户端Mock,工作原理是在客户端拦截JavaScript代码发出的ajax请求并返回由Mock.js创建的假数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<script src="/libs/js/mock.js"></script>
<script>
Mock.mock('/api',{
'code|1':{
200,
404,
500
},
'errMsg|1':[
'资源未找到',
'服务器错误'
],
'data':{
'a':1
}
})
loading=true;
$.ajax({
url:'/api',
dataType:'jsonp',
success(res){
if(res.code===200&&res.response){
data=res.response.data
}else{
alert(res.errMsg)
}
},
fail(){
alert('操作失败')
},
complete(){
loading=false;
}
})
</script>

Mock.js可以随机创建假数据,还可以处理各种异常状态,然而几遍客户端Mock提供了许多便利,Mock相关代码或文件仍然必须存在于业务代码中,上线之前仍然需要删除,这对于产品质量保障始终存在一定隐患。

3 Mock Server

在开发阶段使用Mock Server提供的与真实接口规范和逻辑一致的本地接口进行开发

开发完成后,在构建阶段将Mock的地址修改为已完成的真实服务器端接口地址

Mock Server最普遍的使用场景就是模拟异步数据接口,比如使用Ajax或者JSONP获取和提交数据,模拟的方式通常有两种:

  • Local:本地模式,使用本地JSON数据作为异步接口的请求响应
  • Proxy:代理模式,将异步接口代理到线上的其他接口地址,类似于转接者角色

Mock Server本质上是一个简化版的Web Server,最基础的组件就是负责分发的路由

Local模式:

在开发阶段使用本地API代替真实API地址,使用本地JSON作为接口的返回数据,具体搭建流程:

通过路由创建一个可访问的本地域名API代替真实API,比如使用/login代替http://auth.app.com/login

在路由响应函数内对请求进行校验,比如是否为JSONP请求,然后返回本地JSON数据

前端工程师在开发阶段的业务代码中将http://auth.app.com/login修改为API/login

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const Path=require('path')
const express=require('express')
const app=express()
app.get('/login',(req,res)=>{
//path.join(process.cwd())//返回的是当前Node.js进程执行时的工作目录
const MockData=require(path.join(process.cwd(),'./mockdata.login.js'));
req.query.callback?res.jsonp(MockData):res.json(MockData);

}
);
app.listen(8888,err=>{
if(err){
throw new Error(err)
}
})

DefinePlugin和环境变量

开发环境使用Mock Server将所有真实接口地址修改为本地域名地址,在部署测试和生产环境之前必须将接口的地址复原。

接口地址的修改需求涉及两个方面:

执行环境:开发,测试,生产环境下的接口地址均不同,所以必须能够依据部署目标环境将接口修改为对应地址

字符串修改:对于JavaScript代码来说,接口地址就是一个字符串,我们要做的就是将该字符串修改为指定的值

1
2
3
4
5
6
7
8
9
entry:{
'main.app':'./js/main.app.js'
},
plugins:[
new webpack.DefinePlugin({
AUTH_API_DOMAIN:'//auth.app.com',
HMOE_API_DOMAIN:'//www.app.com'
})
]

源代码

1
2
3
4
5
6
7
8
9
10
//请求位于auth.app.com域名下的login接口
$.ajax({
url:`${AUTH_API_DOMAIN}/login`,
success(res){}
})
//请求位于www.app.com域名下的login接口
$.ajax({
url:`${HOME_API_DOMAIN}/login`,
success(res){}
})

经过构建后

1
2
3
4
5
6
7
8
9
10
//请求位于auth.app.com域名下的login接口
$.ajax({
url:`//auth.app.com/login`,
success(res){}
})
//请求位于www.app.com域名下的login接口
$.ajax({
url:`//www.app.com/login`,
success(res){}
})

结合环境变量,配置DefinePlugin指定不同环境下的替换值

1
2
3
4
new webpack.DefinePlugin({
AUTH_API_DOMAIN:process.env.NODE_ENV==='dev'?'':'//auth.app.com',
HOME_API_DOMAIN:process.env.NODE_ENV==='dev'?'':'//www.app.com'
})

以上代码在开发环境下将接口映射到本地的Mock Server,非开发环境下修改为真实域名的地址