React 代理配置(五)
React 官网链接:
接着上节 React 脚手架介绍(create-react-app)(四)
代理
代理介绍
代理,顾名思义,就是代替你去操作
譬如现在有两个角色,客户端与服务端
- 如果不借助代理:客户端直接与服务端通信
- 如果借助代理:客户端跟代理说需求,代理去跟服务端通信
举个场景例子:(正向代理)
我:客户端 厨师:服务端 服务员:代理
- 如果不借助代理:我(客户端)直接跟 厨师(服务端)说要吃什么
- 如果借助代理:我(客户端)跟 服务员(代理)说要吃什么,服务员(代理)再去和厨师(服务端)说
正向代理
**正向代理( Forward Proxy )**是一个位于 客户端 和 原始服务器 之间的 服务器,客户端 为了从 原始服务器 取得内容,向代理发送一个请求并指定目标(原始服务器),然后 代理 向 原始服务器 转交请求并将获得的内容返回给客户端
简单来说:一个服务员(Proxy)服务多个客户(Client),将他们点的菜都交给这个厨师(Server)
图示如下:
- Client(多个客户),Proxy (服务员),Server(一个厨师)
说明:
- 代理代理客户,为客户端收发请求,隐藏了真实的客户,客户端对服务端不可见
- 一个局域网内的所有用户可能被一台服务器做了正向代理,由该台服务器负责 HTTP 请求
- 与服务器做通信的是 正向代理服务器
反向代理
反向代理( Reverse Proxy ) 是指以 代理服务器 来接受 Internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 Internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器
简单来说:多个客户(Client)都在下单系统(Proxy)下单,下单系统(Proxy)将它们点的菜进行分配,多个厨师(Server)谁有时间谁做
图示如下:
- Client(多个客户),Proxy (下单系统),Server(多个厨师)
说明:
- 代理服务器,隐藏了真实的服务器,为服务器收发请求,真实服务器对客户端不可见
- 负载均衡服务器,将用户的请求分发到空闲的服务器上。
代理总结
正向代理与反向代理的共同点与区别如下:
-
共同点:
- 都是做为服务器和客户端的中间层
- 都可以加强内网的安全性,阻止 Web 攻击
- 都可以做缓存机制,提高访问速度
-
区别:
- 正向代理其实是客户端的代理,反向代理则是服务器的代理
- 正向代理中,服务器并不知道真正的客户端到底是谁;而在反向代理中,客户端也不知道真正的服务器是谁。
- 正向代理与反向代理使用场景不同,正向代理主要是用来解决访问限制问题(跨域); 而反向代理则是提供负载均衡、安全防护等作用。
举个例子:
- 我们访问google访问不了,买一些代理,帮助我们突破限制能够访问google,即正向代理
- 后端部署了很多相同的应用,前端都可对其进行访问,访问哪个服务器得到的结果都是一样。譬如双11的时候,很多人都去访问服务器,若有多个服务器的时候,谁能干就谁处理,但是前端并不知道谁处理的,即反向代理
代理配置
在React 项目中(这里指的是根据脚手架创建的项目),在 npm start 启动的时候
默认是 localhost:3000 为项目访问地址
如果需要配置代理,在React 有两种方式:
- 简单配置(现有配置文件中配置代理)
- 复杂配置(新建配置文件配置代理)
1、简单配置 (借助 package.json)
例如我们的后端启动端口是 5000,React项目启动是 3000,若想访问 5000 的资源,会涉及跨域问题(如果后端允许,也可能不会遇到),若遇到跨域问题,需要进行正向代理的配置
第一种简单配置即直接在 package.json 的末尾中加上 proxy
"proxy":"http://localhost:5000"
说明:
- 优点:配置简单,前端请求资源时可以不加任何前缀。
- 缺点:不能配置多个代理。
- 工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000
注意点:虽然配置了代理,但在真实访问的时候会优先匹配前端资源,即如果根据资源路径在前端可以找到对应资源文件,即优先访问前端的资源文件
2、复杂配置(新建 setupProxy.js 文件)
这个与上面的代理配置相比会稍微复杂一点,主要分为两个步骤
- 创建代理配置文件
- 配置具体代理规则
第一步:创建代理配置文件
在src下创建配置文件:src/setupProxy.js
第二步:编写 setupProxy.js 配置具体代理规则
- proxy 即配置代理(两个参数)
- 第一个参数:需要转发的请求前缀(
- 例如:localhost:3000/api1/xxxx 这样的地址即转发为 localhost:5000/api1/xxxx
- 第二个参数:一个对象{} ,包含多个key : value
- target:遇到该路径前缀转发的目标地址
- changeOrigin:控制服务器接收到的请求头中host字段的值(true / false来表示是否隐藏真实来源)
- pathRewrite:去除前缀配置,这个前缀是前端定义的,如果后端路径没有这个前缀,就需要去除
- 若不配置:那 localhost:3000/api1/xxxx 这样的地址即转发为 localhost:5000/api1/xxxx
- 若配置了:那localhost:3000/api1/xxxx 这样的地址即转发为 localhost:5000/xxxx
- 第一个参数:需要转发的请求前缀(
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
app.use(
// 第一个代理
proxy('/api1', { //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给下面的target)
target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
changeOrigin: true,
/*
changeOrigin 为 控制服务器接收到的请求头中host字段的值
changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000(隐藏真实来源)
changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
默认值为false,一般将changeOrigin值设为true
*/
pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
}),
// 第二个代理
proxy('/api2', {
target: 'http://localhost:5001',
changeOrigin: true,
pathRewrite: {'^/api2': ''}
})
)
}
说明:
- 优点:可以配置多个代理,可以灵活的控制请求是否走代理
- 缺点:配置繁琐,前端请求资源时必须加前缀
总结
代理在实际开发中很有必要
一般情况下,前端配置一个代理即可(即采用第一种简单配置),如果涉及很多代理,可以让后端利用一些例如 Apache / Nginx 这种去做正向代理,给前端一个域名,后端根据具体的路径前缀去指定不同的应用,也是可以的~(比较常用)