webpack-dev-server原理解析及跨域解决方法
作者:背太阳的牧羊人
webpack proxy ,就是 webpack 提供的解决跨域的方案。其基本行为是接受客户端发送的请求后转发给其他的服务器,目的是为了解决在开发模式下的跨域问题。
原理
webpack中的proxy 工作原理是利用了 http-proxy-middleware
这个http 代理中间件,实现将请求转发给其他的服务器。
如下:在开发阶段,本地地址是 Http://loaclhost:3000
, 该浏览器发送一个前缀带有 /api 标识的向服务器请求数据,但是这个服务器只是将这个请求转发给另一台服务器:
const express = require('express'); const proxy = require('http-proxy-middleware'); const app = express(); app.use('/api', proxy({target: 'http://www.test.org', changeOrigin: true})); app.listen(3000); // http://localhost:3000/api/foo/bar -> http://www.test.org/api/foo/bar
在开发阶段,webpack-dev-server 会自动启动一个本地开发服务器,所以我们的应用在开发阶段是独立运行在 localhost 的一个端口上的,而后端服务器又是运行在另一个地址上.。
所以在开发阶段中,由于浏览器的同源策略,当本地浏览器访问后端服务器的时候就会出现跨域请求资源的问题。
通过设置 webpack proxy 实现代理请求后,相当于浏览器和服务器之间添加了一个代理服务器。
当本地发送请求的时候,中间服务器会接受这个情求,并将这个请求转发给目标服务器(也就是后端服务器),目标服务器返回数据后,中间服务器又会将数据返回给浏览器,当中间服务器将数据返回给服务器的时候,它们两者是同源的,并不会存在跨域的问题。
服务器和服务器之间是不会存在跨域资源的问题的。
webpack-dev-server
webpack 提供代理服务器的工具是webpack-dev-server
,但只适用于开发阶段,线上要实现代理一般通过 nginx 来配置。
webpack 中的服务器工具 webpack-dev-server,实质上是启动了一个 express 服务器。
proxy 代理是利用 http-proxy-middleware
这个http代理中间件实现将请求转发给其他服务器。
(vite 是用的 http-proxy,其实 http-proxy-middleware 也是基于 http-proxy 的)
背后其实都是使用 node 来启动 server 服务器,这也是为什么我们常说这种代理只能在开发阶段使用,因为 build 生产包时我们并不会打包一个 node 服务器进去,线上要实现代理一般直接通过 nginx 来配置。
可以在webpack 配置对象属性中通过 devServer 属性来配置:
// ./webpack.config.js const path = require('path') module.exports = { // ... devServer: { contentBase: path.join(__dirname, 'dist'), compress: true, port: 9000, proxy: { '/api': { target: 'https://api.github.com' } } // ... } }
webpack-dev-server常用的配置项
Proxy代理
它的目的是设置代理来解决跨域访问的问题。举例:
我们的一个api请求地址(也就是服务器地址)是 http://localhost:8888
,
但是本地启动服务器的域名是 http://localhost:8000
,
这个时候发送网络请求就会出现跨域的问题(端口不同)。
所以将请求先发送到一个代理服务器,代理服务器和API服务器没有跨域的问题,就可以解决我们的跨域问题了。
module.exports = { //... devServer: { proxy: { '/api': {// 以 /api 开头的请求,会转发到下面的 target 配置 target: 'http://localhost:8888',// 目标服务器 pathRewrite: { "^/api": "", // 重写路径为空,即请求路径中没有/api字符串 "^/api": "/abcd" // 重写路径为abcd,即将请求路径中的/api字符串替换成/abcd }, secure: false,// https接口,需要配置这个参数 changeOrigin: true,// 将请求头中的host 配置为 target }, }, host: '0.0.0.0', //用于指定devDerve使用的host,如果你希望服务器外部可以访问,设定如 host: '0.0.0.0' https: true, // 默认情况下dev-server使用http协议,通过配置可以支持https, // 注意:默认使用自签名证书,也可以配置自己的证书 // https: { // ca: './path/to/server.pem', // pfx: './path/to/server.pfx', // key: './path/to/server.key', // cert: './path/to/server.crt', // passphrase: 'webpack-dev-server', // requestCert: true, // }, // 开启热模块替换 hot: true, }, };
- target:表示的是代理到的目标地址(也就是要访问的服务器地址),比如 /api会被代理到 http://localhost:8888/api
- pathRewrite:默认情况下,我们的 /api 也会被写入到URL中,即:http://localhost:8888/api, 如果希望删除,可以使用pathRewrite,比如:
- 配置成 "^/api": "",那么/api/user => http://localhost:8888/user,地址中没有/api,因为重新路径是空的;
- 配置成"^/api": "/abcd" ,那么/api/user => http://localhost:8888/abcd/user,即将请求路径中的/api字符串替换成/abcd
- secure: 默认情况下,不接受在 HTTPS 上运行且证书无效的后端服务器。 https接口,需要配置这个参数为false;
- changeOrigin:它表示是否更新代理后请求的headers中host地址,一般设置为true
proxy
配置中 changeOrigin: true
,// 将请求头中的host 配置为 target。
那为什么要更改请求头中的host呢?
因为一台服务器上可以部署多个项目,当我们发送请求时,DNS 会将域名解析为 IP 地址,此时,也就确定了我们目标服务器,那如何确定我们要访问的是哪个项目呢?这就需要用到 host 字段了。
请求头中Host用来指定请求的 域名/ip地址和端口号,通常用于指定服务器的地址,端口号可以省略,省略时默认为80端口。
此时我们将host指定为a.com就会访问到淘宝服务了。
所以如果一台服务器上部署多个项目时,我们需要更改请求头中的host,来指定我们要访问的项目。
一台服务器只有一个项目时,我们可以不用更改请求头中的host,因为DNS解析后,就确定了我们要访问的项目。
但为了以后用起来方便,就统一将这个配置项changeOrigin设置为true。
host
devServer.host
配置项⽤于配置 DevServer 服务监听的地址,默认使⽤ 8080 端⼝。 如果 8080 端⼝ 已经被其它程序占有就使⽤ 8081,如果 8081 还是被占⽤就使⽤ 8082,以此类推
例如:
你想要局域⽹中的其它设备访问你本地的服务,可以在启动 DevServer 时带上 --host 0.0.0.0
,
也可以在webpack
配置项devServer.host
中设置0.0.0.0
host 的默认值是 127.0.0.1
即只有本地可以访问 DevServer 的 HTTP 服务。
localhost 和 0.0.0.0 的区别:
localhost:本质上是一个域名,通常情况下会被解析成127.0.0.1。127.0.0.1:回环地址(Loop Back Address),表达的意思其实是我们主机自己发出去的包,直接被自己接收。
正常的数据库包经过 应用层 - 传输层 - 网络层 - 数据链路层 - 物理层 ,而回环地址,是在网络层直接就被获取到了,是不会经过数据链路层和物理层的。
比如:
我们监听 127.0.0.1时,在同一个网段下的主机中,通过ip地址是不能访问的。
0.0.0.0:监听IPV4上所有的地址,再根据端口找到不同的应用程序,比如我们监听 0.0.0.0时,在同一个网段下的主机中,通过ip地址是可以访问的
port、open、compress
devServer.port
设置监听的端口,默认情况下是8080,不能设置为null,可以设置自动为auto
module.exports = { //... devServer: { port: 8080, }, };
devServer.open
告诉 dev-server 在服务器已经启动后打开浏览器。设置其为 true 以打开你的默认浏览器。
module.exports = { //... devServer: { open: true, //在浏览器中打开指定页面:open: ['/my-page'] //提供要使用的浏览器名称,而不是默认名称 // open: { // app: { // name: 'google-chrome', // }, // }, }, };
devServer.compress
告诉 dev-server 在服务器端启用 gzip 压缩,用于减少服务器向前端传输的数据量,提高浏览的速度。
module.exports = { //... devServer: { compress: true, }, };
到此这篇关于webpack-dev-server原理解析及其中跨域解决方法的文章就介绍到这了,更多相关webpack-dev-server原理解析及其中跨域解决方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!