webpack proxy ,就是 webpack 提供的解决跨域的方案。其基本行为是接受客户端发送的请求后转发给其他的服务器,目的是为了解决在开发模式下的跨域问题。
原理
webpack中的proxy 工作原理是利用了
如下:在开发阶段,本地地址是
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 中的服务器工具 webpack-dev-server,实质上是启动了一个 express 服务器。
proxy 代理是利用
(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请求地址(也就是服务器地址)是
但是本地启动服务器的域名是
这个时候发送网络请求就会出现跨域的问题(端口不同)。
所以将请求先发送到一个代理服务器,代理服务器和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
那为什么要更改请求头中的host呢?
因为一台服务器上可以部署多个项目,当我们发送请求时,DNS 会将域名解析为 IP 地址,此时,也就确定了我们目标服务器,那如何确定我们要访问的是哪个项目呢?这就需要用到 host 字段了。
请求头中Host用来指定请求的 域名/ip地址和端口号,通常用于指定服务器的地址,端口号可以省略,省略时默认为80端口。
此时我们将host指定为a.com就会访问到淘宝服务了。
所以如果一台服务器上部署多个项目时,我们需要更改请求头中的host,来指定我们要访问的项目。
一台服务器只有一个项目时,我们可以不用更改请求头中的host,因为DNS解析后,就确定了我们要访问的项目。
但为了以后用起来方便,就统一将这个配置项changeOrigin设置为true。
host
例如:
你想要局域?中的其它设备访问你本地的服务,可以在启动 DevServer 时带上
也可以在
host 的默认值是
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
module.exports = { //... devServer: { port: 8080, }, };
module.exports = { //... devServer: { open: true, //在浏览器中打开指定页面:open: ['/my-page'] //提供要使用的浏览器名称,而不是默认名称 // open: { // app: { // name: 'google-chrome', // }, // }, }, };
module.exports = { //... devServer: { compress: true, }, };
参考