JavaScript跨域是浏览器基于同源策略主动拦截请求,协议、域名、端口任一不同即触发;核心错误“No 'Access-Control-Allow-Origin' header”源于浏览器收到响应后校验失败,需后端正确处理预检OPTIONS并返回合法CORS头。

什么是 JavaScript 跨域?
JavaScript 跨域不是“代码写错了”,而是浏览器主动拦截了本该发出的请求。核心判断依据是:协议、域名、端口三者中任意一个不同,就算跨域。https://a.com 请求 https://b.com/api 会被拦;http://localhost:3000 请求 http://localhost:8080 同样被拦——端口不同也算跨域。
为什么 fetch / XMLHttpRequest 会报 “No 'Access-Control-Allow-Origin' header”?
这个错误不是后端没收到请求,而是浏览器在收到响应后,发现响应头里没有 Access-Control-Allow-Origin,就拒绝把响应结果交给 JS。关键点在于:浏览器先发预检请求(OPTIONS),后端必须正确响应它,才能放行后续的 GET 或 POST。
常见疏漏:
- 只给主接口加 CORS 头,忘了处理
OPTIONS预检 -
前端带了
Credentials(比如withCredentials: true),但后端返回的Access-Control-Allow-Origin: *不合法——必须指定具体域名 - 后端设置了
Access-Control-Allow-Headers,但漏了前端实际发送的自定义头(如X-Auth-Token)
开发阶段最稳妥的代理方案(Vite / Webpack DevServer)
不改后端、不碰浏览器策略,靠本地开发服务器转发请求,让浏览器认为“还是同源”。重点不是“配代理”,而是配对路径和重写规则。
立即学习“Java免费学习笔记(深入)”;
Vite 示例(vite.config.ts):
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
注意:changeOrigin: true 必须开,否则后端收到的 Host 头还是前端地址;rewrite 是为了去掉 /api 前缀,否则后端收不到真实路径。
生产环境不能依赖代理,得看后端怎么配 CORS
前端改不了跨域限制,最终必须由后端响应正确的 CORS 头。典型配置项:
-
Access-Control-Allow-Origin:可填具体域名(如https://myapp.com),不能填*+credentials -
Access-Control-Allow-Credentials:设为true时,前端才能传 cookie 或 authorization -
Access-Control-Allow-Methods:列出允许方法,如GET, POST, PUT, DELETE -
Access-Control-Allow-Headers:列出前端可能带的头,如Content-Type, Authorization
如果后端用 Express,常用中间件是 cors,但别直接 app.use(cors()) —— 默认允许所有源,不安全。应显式配置:
app.use(cors({
origin: 'https://myapp.com',
credentials: true,
allowedHeaders: ['Content-Type', 'Authorization']
}));
跨域真正麻烦的地方不在“怎么配”,而在于前后端对同一场景的理解错位:前端以为发出去了,其实被浏览器吞了;后端以为没收到请求,其实预检就被拒了。查问题先看 Network 面板里有没有 OPTIONS 请求,再看它的响应头。











