前端开发中如何解决跨域问题
在前端开发中,动不动就会出现跨域的问题,导致网络请求不成功,对于前后端分离的项目更是如此,这期视频我们就看一下跨域是什么,如何解决跨域问题。
什么是跨域
跨域全称是跨域资源共享(Cross-Origin Resources Sharing, CORS),它是浏览器的保护机制,只允许网页请求同一域名下的服务,同一域名的要求是,协议、域名和端口都要保持一致:
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:配置后端
浏览器是否启用跨域保护机制是根据后端的响应来定的,所以配置后端是最直接的一种方法,浏览器根据的是响应的Access-Control-Allow-Origin
响应头来决定的:
如果这个字段的值是"*",那么会允许所有请求,如果是一个域名,那么浏览器就不会对这个域名下的请求进行跨域保护:
Access-Control-Allow-Origin: http://localhost:3000
根据后端程序的语言和库的不同,配置 Access-Control-Allow-Origin
响应头的方法也不同,如果使用的是 node.js 和 express,那么可以添加 cors 中间件:
const cors = require("cors");
app.use(cors());
cors 默认会允许所有跨域请求,如果要限制指定域名,可以给它的 origin 配置项传递一个字符串或数组,用于指定一个或多个允许跨域的域名:
app.use(cors({ origin: ["http://domain1.com", "http://domain2.com"] }));
方法 2:配置前端
第 2 种方法,是在前端开发环境中,配置代理,中转请求,因为跨域是浏览器的保护机制,如果脱离的浏览器发送请求,是不会受到跨域保护机制的影响的,所以我们可以使用一个中转服务器来发送和接收请求,前端只需要请求这个中转服务器,并保持和中转服务器的 URL 保持一致即可。
一般的前端脚手架工具都支持配置代理,例如 vite、create react app 等,这里以 vite 为例, vite 自带的开发服务器支持设置代理,在 vite.config.js 文件里,我们可以配置 server 配置项下的 proxy 配置,把对 /api 路径的请求代理转发到真实的后端服务路径,再根据需要,对转发的 URL 进行改写。
server: { proxy: { "/api": { target: "http://localhost:5000", changeOrigin:
true, rewrite: (path) => path.replace(/^\/api/, ""), }, }, },
这里的配置项把前端请求的 /api 路径转发到 http://localhost: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
我们可以使用 express 来创建一个服务器,负责发送前端页面,并代理请求。例如我们这里把让请求都返回 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-middleware
依赖库,它和 vite 底层使用的代理服务是一样的,配置也几乎一样,不同的是 vite 中 rewrite 配置项这里叫作 pathRewrite:
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
除了使用 express,也可以使用 nginx 等专业的服务器程序,你可以参考相关文档来配置代理。
小结
好了,这个就是如何解决前端跨域的方法,你学会了吗?如果有帮助请三连,想学更多有用的前端开发知识,请关注峰华前端工程师,感谢观看!
一系列的课程让你成为高级前端工程师。课程覆盖工作中所有常用的知识点和背后的使用逻辑,示例全部都为工作项目简化而来,学完即可直接上手开发!
即使你已经是高级前端工程师,在课程里也可能会发现新的知识点和技巧,让你的工作更加轻松!
《React 完全指南》课程,包含 React、React Router 和 Redux 详细介绍,所有示例改编自真实工作代码。点击查看详情。
《Vue 3.x 全家桶完全指南与实战》课程,包括 Vue 3.x、TypeScript、Vue Router 4.x、Vuex 4.x 所有初级到高级的语法特性详解,让你完全胜任 Vue 前端开发的工作。点击查看详情。
《React即时通信UI实战》课程,利用 Storybook、Styled-components、React-Spring 打造属于自己的组件库。
《JavaScript 基础语法详解》本人所著图书,包含 JavaScript 全面的语法知识和新特性, 可在京东、当当、淘宝等各大电商购买