持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情
webpack-dev-server 是一个基于 Express 的本地开发服务器。它使用 webpack-dev-middleware 中间件来为通过 Webpack 打包生成的资源文件提供 Web 服务。它还有一个通过 Socket IO 连接着 webpack-dev-server 服务器的小型运行时程序。webpack-dev-server 发送关于编译状态的消息到客户端,客户端根据消息作出响应。
基本配置
webpack-dev-server 被 Webpack 作为内置插件对外提供,这样可以直接在对应的 Webpack 配置文件中通过devServer这个属性的配置来配置自己的webpack-dev-server。webpack-dev-server 的配置文件参考webpack-devServer。
// package.json
"scripts": {
"dev": "webpack serve"
}
// webpack.config.js
const path = require('path');
module.exports = {
//...
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 9000,
},
};
下面对一些重要配置项进行简单说明:
- https: true: devServer默认是通过http发送请求,如果你想使用https需要进行设置。
- hot: true: 模块热替换(HMR - hot module replacement)功能会在应用程序运行过程中,替换、添加或删除模块,而无需重新加载整个页面。
- open: true: 当启动时直接打开默认浏览器
- compress: true: 服务开启 Gzip 压缩
- host: '0.0.0.0': 使用
0.0.0.0可以让局域网内可访问
proxy
在实际开发中,本地开发服务器是不能直接请求线上数据接口的,这是因为浏览器的同源安全策略导致的跨域问题,我们可以使用devServer.proxy来解决本地开发跨域的问题。
下面的配置是将页面访问的/api所有请求都转发到了baidu.com上:
module.exports = {
//...
devServer: {
proxy: {
'/api': 'http://baidu.com'
}
}
};
那么,我们请求/api/users则会被转发到http://baidu.com/api/users线上地址。
devServer.proxy的值还支持高级属性,通过高级属性我们可以做更多的事情,如上面的需求变成,将/api/users转发到 baidu.com/users, 那么配置就需要改成:
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'http://baidu.com',
pathRewrite: {'^/api': ''}
}
}
}
};
如果我们需要转发的网站是支持 https 的,那么需要增加secure=false,来防止转发失败:
secure: false
又有新的需求了,这时候只能代理json接口的数据,对于html文件,还是使用打包后 dist 文件夹中文件,那么我们使用bypass(绕过)来实现这个需求:
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'http://baidu.com',
bypass(req, res, proxyOptions) {
// 判断请求头中的 accept 值
if (req.headers.accept.indexOf('html') !== -1) {
console.log('Skipping proxy for browser request.');
// 返回的是 contentBase 的路径
return '/index.html';
}
}
}
}
}
};
函数返回值:
- 如果返回
nullorundefined,说明还是走正常的代理 - 如果返回
false,将直接返回404的错误,结束代理 - 如果返回一个路径(return '/index.html'),说明代理结束,不会走后面的代理逻辑
自定义中间件
在 webpack-dev-server 中有两个时机可以插入自己实现的中间件,分别是在devServer.before和devServer.after两个时机,即 webpack-dev-server 加载所有内部中间件之前和之后两个时机。
module.exports = {
//...
devServer: {
before(app, server) {
app.get('/some/path', (req, res) => {
res.json({custom: 'response'});
});
}
}
};
自定义中间件在开发中常常被用来当作 mock server 使用。
mock server 现在的前端团队一般都会采取前后端分离的开发模式,这样可以做到前后端同时并行开发,而前端同学开发的时候需要依赖后端同学提供的数据接口,后端同学的数据接口没有开发完成的时候,前端不能傻傻的等着,所以这就需要一个 mock server 来根据前后端接口的约定格式伪造一些假数据,这样前端开发就可以继续下去,加快开发进度。
webpack-dev-server 提供了自定义中间件的 Hook,所以我们可以很简单的实现自己的 mock server。下面代码是在devServer.before插入一个接口/api/mock.json的接口响应:
module.exports = {
//...
devServer: {
port: 9000,
before(app, server) {
app.get('/api/mock.json', (req, res) => {
res.json({hello: 'world'});
});
}
}
};
启动 dev server,访问 http://localhost:9000/api/mock.json就可以看到这个接口返回的数据了。