一、前言
做前端开发,跨域绝对是绕不开的问题。本地开发、联调后端、部署上线、面试,几乎处处都会遇到:
- 控制台报错:
No 'Access-Control-Allow-Origin'... - 请求发出去了,浏览器就是拿不到数据
- 面试官一问跨域,只能说出 CORS
这篇文章从原理 → 为什么会跨域 → 所有解决方案,从零到一讲明白,看完彻底吃透跨域。
二、什么是跨域?
先记住一句话:跨域,是浏览器的安全策略限制,不是后端限制,也不是网络限制。
1. 同源策略(Same-Origin Policy)
浏览器为了安全,规定:只有协议、域名、端口完全一致,才叫「同源」,否则就是跨域。
对比一下:
当前页面:http://www.test.com:8080/index.html
| 请求地址 | 是否跨域 | 原因 |
|---|---|---|
http://www.test.com:8080/api |
不跨域 | 完全一样 |
https://www.test.com:8080/api |
跨域 | 协议不同(http/https) |
http://api.test.com:8080/api |
跨域 | 域名不同 |
http://www.test.com:9090/api |
跨域 | 端口不同 |
只要有一个不一样,浏览器就会拦截响应,报跨域错误。
2. 关键点
- 跨域请求能发出去,后端也能收到并返回
- 是浏览器拦截了响应,不给前端用
- 服务器之间不存在跨域(只有浏览器有)
三、跨域解决方案(最全、最实用)
我按实际工作使用频率从高到低讲,你工作 99% 只用前 4 个。
1. CORS(最常用、最简单)
CORS:跨域资源共享,后端一行配置搞定。
后端在响应头加:
makefile
Access-Control-Allow-Origin: *
或者指定域名:
arduino
Access-Control-Allow-Origin: http://localhost:8080
简单请求(GET/POST,无自定义头)直接生效。复杂请求(PUT/DELETE/ 自定义头)会先发 OPTIONS 预检请求。
优点 :标准、安全、推荐缺点:需要后端配合
2. 开发环境代理(webpack/vite 代理)
本地开发最常用,前端自己解决,不用找后端。
vite 示例
javascript
// vite.config.js
export default {
server: {
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: path => path.replace(/^/api/, '')
}
}
}
}
原理:本地起个 Node 服务转发请求,服务器之间没有跨域。
3. Nginx 反向代理(上线必备)
线上环境一般用 Nginx 转发,伪装成同源。
ini
server {
listen 80;
server_name localhost;
location /api {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
}
}
前端请求 /api/xxx → Nginx → 真实接口。
4. JSONP(老方案,只支持 GET)
利用 <script src="xxx"> 不受跨域限制。
javascript
function cb(data) {
console.log(data)
}
<script src="http://xxx/api?callback=cb"></script>
后端返回:
css
cb({ name: "test" })
缺点:只支持 GET,不安全,现在基本不用。
5. postMessage(iframe 跨域)
页面与 iframe、多窗口之间跨域通信。
javascript
// 父页面
iframe.contentWindow.postMessage('数据', '*')
// 子页面
window.addEventListener('message', e => {
console.log(e.data)
})
6. WebSocket
WebSocket 不受同源策略限制,可以跨域通信。
7. document.domain、window.name
多用于同主域名不同子域名,现在很少用,了解即可。
四、方案怎么选?(直接照抄)
给你一个工作直接用的选择指南:
- 本地开发:webpack /vite 代理(首选)
- 生产环境:Nginx 代理 或 CORS
- 和后端配合:优先 CORS(标准方案)
- 老系统兼容:JSONP
- iframe 通信:postMessage
五、面试常问(背会直接用)
- 什么是跨域?为什么会有跨域?
- 跨域是浏览器限制还是服务端限制?
- CORS 简单请求和复杂请求区别?
- OPTIONS 请求是什么?
- 本地开发怎么解决跨域?
- JSONP 原理和缺点?
把这篇文章看完,这些问题全能答出来。
六、总结
- 跨域 = 浏览器同源策略限制
- 请求能发,响应被浏览器拦了
- 工作常用:CORS、开发代理、Nginx 代理
- 面试必考:原理 + CORS + 方案对比