在前后端分离开发中,“跨域问题” 是前端开发中经常遇到的一个难题,本文将系统性地介绍跨域的成因、浏览器的同源策略、常见的解决方案以及正向代理与反向代理的区别。
一、什么是跨域问题?
跨域问题,通常是由于 浏览器的同源策略(Same-Origin Policy) 引起的。
1.1 同源策略的定义
同源是指页面请求的资源必须来自 相同的协议、主机和端口。
举例说明:
-
不同协议:Example Domain ≠ Example Domain
-
不同主机名:Example Domain ≠ http://api.example.com
-
不同端口:http://example.com:8080 ≠ http://example.com:8801
只要这三者中有一个不同,浏览器就会认为是“跨域”。
1.2 为什么会有跨域问题?
在传统的服务端渲染模式下,前端页面和后端 API 通常部署在同一台服务器上,不存在跨域问题。
但随着 前后端分离架构 的兴起,前端项目被独立打包部署,而后端 API 通常部署在另一台服务器或另一个端口。这种部署方式引发了跨域访问,从而被浏览器阻止。
✅ 静态资源服务器和 API 服务器在同一台服务器上时,一般不会有跨域问题。
二、跨域的解决方案
我们常见的解决方案主要有以下几种:
2.1 方案一:CORS(跨域资源共享)
CORS(Cross-Origin Resource Sharing) 是服务器端解决跨域问题的主流方式。
原理:
服务器在响应头中添加如下字段来授权跨域访问:
Access-Control-Allow-Origin: http://localhost:3000
关于预检请求(Preflight Request):
当浏览器发送复杂请求(如 PUT
, DELETE
, 或带有自定义头的请求)时,会先发一个 OPTIONS
请求进行“预检”,确认服务端是否允许实际请求。
如果服务端响应通过,浏览器才会继续发送真正的请求。
2.2 方案二:本地代理服务器(Webpack / Vite)
在开发环境中,我们不能直接修改后端服务器的配置,这时可以借助构建工具内置的代理功能来解决跨域问题。
原理:
无论是 Webpack 还是 Vite,它们都会在本地启动一个 Node.js 服务,通过代理转发请求到目标 API 服务器。
// Vite 示例
export default {
server: {
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
}
效果:
前端请求 /api/user
,由本地开发服务器拦截并代理转发为 http://localhost:5000/user
,浏览器不会报跨域错误。
2.3 方案三:Nginx 反向代理
在生产环境中,我们可以使用 Nginx 来配置反向代理,解决跨域问题。
情况一:Nginx 同时代理静态资源和 API 服务
server {
listen 80;
server_name example.com;
location / {
root /var/www/frontend;
index index.html;
}
location /api/ {
proxy_pass http://backend-server:5000/;
proxy_set_header Host $host;
}
}
情况二:Nginx 仅代理 API 服务(前端通过 CDN 或其他服务器加载)
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://localhost:5000;
}
}
三、正向代理与反向代理的区别
项目 | 正向代理 | 反向代理 |
---|---|---|
代理对象 | 客户端 | 服务端 |
使用场景 | 客户端访问受限资源,如翻墙 | 客户端无需感知后端真实服务器 |
客户端是否知道代理 | 是 | 否 |
常见用途 | 科学上网,缓存请求等 | 负载均衡,隐藏真实服务器,解决跨域 |
四、总结
解决方案 | 适用环境 | 优势 | 注意事项 |
---|---|---|---|
CORS | 开发 + 生产 | 主流、安全、标准方式 | 需要后端支持配置 |
本地代理 | 开发 | 快速、方便 | 仅适用于本地开发 |
Nginx代理 | 生产 | 性能好、可拓展 | 需要配置服务器,掌握Nginx语法 |
欢迎来Caa · 语雀,每日更新前端知识ing,一起学习进步!