在前端开发中,动不动就会出现跨域的问题,导致网络请求不成功前端跨域解决方案,对于前后端分离的项目更是如此,这期视频我们就看一下跨域是什么,如何解决跨域问题。
什么是跨域
跨域全称是跨域资源共享(Cross- , CORS),它是浏览器的保护机制,只允许网页请求同一域名下的服务,同一域名的要求是,协议、域名和端口都要保持一致:
<span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_png/o5A9q1yjibibMtSy7X11S3dnFuiaJ4kniaFxUzEf1FQCSftAcQY0Sia8jBOta50UvOaQx85nfoJaIUmSQbianZKbda9g/640?wx_fmt=png") 10px 10px / 40px no-repeat rgb(248, 248, 248);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;">http://domain.com -> http://domain.com/api/user
如果有一项不同,那么就是跨域请求:
http://domain.com:3000 -> http://domain.com:5000/api/user http://domain.com ->
https://domain.com/api/user http://domain.com -> http://otherdomain.com/api/user
在前后端分离的项目中,解决跨域可以从 3 种情况下手:
对于传统使用 jsonp 的形式,由于不适合 react 或 vue 之类的开发,并且也有安全隐患,这里就不作介绍了。
方法 1:配置后端
浏览器是否启用跨域保护机制是根据后端的响应来定的前端跨域解决方案,所以配置后端是最直接的一种方法,浏览器根据的是响应的--Allow- 响应头来决定的:
如果这个字段的值是"*",那么会允许所有请求,如果是一个域名,那么浏览器就不会对这个域名下的请求进行跨域保护:
Access-Control-Allow-Origin: http://localhost:3000
根据后端程序的语言和库的不同,配置 --Allow-响应头的方法也不同,如果使用的是 node.js 和 ,那么可以添加 cors 中间件:
const cors = require("cors");
app.use(cors());
cors 默认会允许所有跨域请求,如果要限制指定域名,可以给它的 配置项传递一个字符串或数组,用于指定一个或多个允许跨域的域名:
app.use(cors({ origin: ["http://domain1.com", "http://domain2.com"] }));
方法 2:配置前端
第 2 种方法,是在前端开发环境中,配置代理,中转请求,因为跨域是浏览器的保护机制,如果脱离的浏览器发送请求,是不会受到跨域保护机制的影响的,所以我们可以使用一个中转服务器来发送和接收请求,前端只需要请求这个中转服务器,并保持和中转服务器的 URL 保持一致即可。
一般的前端脚手架工具都支持配置代理,例如 vite、 react app 等,这里以 vite 为例, vite 自带的开发服务器支持设置代理,在 vite..js 文件里,我们可以配置 配置项下的 proxy 配置,把对 /api 路径的请求代理转发到真实的后端服务路径,再根据需要,对转发的 URL 进行改写。
server: { proxy: { "/api": { target: "http://localhost:5000", changeOrigin:
true, rewrite: (path) => path.replace(/^/api/, ""), }, }, },
这里的配置项把前端请求的 /api 路径转发到 :5000/,并把 /api 这一段删除,因为这里后端提供的 API 中不带 /api 这一段:
/api -> http://localhost:5000 /api/user -> http://localhost:5000/user
这样在开发的时候,就避免了跨域问题。前端应用中可以直接请求 proxy 中配置的 /api 来请求后端服务,不用再写前边的协议、域名和端口了,因为默认是和前端相同的:
fetch("/api");
这个时候,如果去掉后端的跨域支持,前端仍然能请求后端的数据:
// const cors = require("cors");
// app.use(cors());
方法 3:产品环境
对于产品环境,或者开发服务器不支持代理的情况下,我们可以自己手动创建一个中转服务器来代理请求。假设我们打包好的前端项目放到了 dist 目录下,入口文件为 index.html:
dist |-- index.html
我们可以使用 来创建一个服务器,负责发送前端页面,并代理请求。例如我们这里把让请求都返回 dist 下的 index.html 文件:
app.use(express.static("dist"));
// serve index.html for all routes
app.get("*", (req, res) => {
res.sendFile(__dirname + "/dist/index.html");
});
但是对于 /api 这个路径,我们还是需要配置代理,这里需要安装 http-proxy- 依赖库,它和 vite 底层使用的代理服务是一样的,配置也几乎一样,不同的是 vite 中 配置项这里叫作 :
const { createProxyMiddleware } = require("http-proxy-middleware");
app.use(
"/api",
createProxyMiddleware({
target: "http://localhost:5000",
changeOrigin: true,
// 这里是 pathRewrite,跟 vite 不太一样
pathRewrite: (path) => path.replace(/^/api/, ""),
})
);
这样,我们再启动这个服务器来负责展现前端产品环境的页面,可以看到,仍然可以成功的请求的后端的数据。
node server_production.js
除了使用 ,也可以使用 nginx 等专业的服务器程序,你可以参考相关文档来配置代理。
小结
好了,这个就是如何解决前端跨域的方法,你学会了吗?
如果有帮助,就点个「赞、在看」吧!
点击阅读原文/扫码查看B站配套视频文本、技术教程、实战课程、资源导航以及小工具!