浏览器HTTP缓存规则导致的跨域
现象
- 两个域名
- localhost:5500(下面简称5500)
- localhost:5501(下面简称5501)
- 后台跨域:正确的配置了5500和5501允许跨域访问
- 当再5500中缓存一个跨域请求后,打开5501后请求相同的请求,结果在5501中出现跨域
⚠️ 在5501中的跨域错误显示的是
Access-Control-Allow-Origin: http://localhost:5500
(???? WTF ???)
猜想
:浏览器的缓存是基于主域名
ts
localhost // 子域名命中: a.localhost,b.localhost...; 不同端口命中: localhost:5500, localhost: 5501...
- test跨域请求
baidu.com // 不同域名互不干扰
- ...
源码
- page1.html
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page1</title>
</head>
<body>
<h1>this is page1.html</h1>
<button onclick="window.open('http://localhost:5501/page2.html')">打开page2</button>
</body>
<script type="module">
const res = await fetch("http://127.0.0.1:3000");
const json = await res.json();
const div = document.createElement("div");
div.innerText = json.message;
document.body.appendChild(div);
</script>
</html>
- page2.html
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page2</title>
</head>
<body>
<h1>this is page2.html</h1>
</body>
<script type="module">
const res = await fetch("http://127.0.0.1:3000");
const json = await res.json();
const div = document.createElement("div");
div.innerText = json.message;
document.body.appendChild(div);
</script>
</html>
- nodejs后台 (我的环境是node v20+)
ts
const { log } = require("console");
const http = require("http");
const server = http.createServer((req, res) => {
const origin = req.headers.origin;
log("origin", req.headers.origin);
res.writeHead(200, {
"Content-Type": "application/json; charset=utf-8",
"Access-Control-Allow-Origin": origin,
"Cache-Control": "private, max-age=60", // 强制缓存60s
});
res.end(JSON.stringify({ message: "Hello, World!" }));
});
server.listen(3000, () => {
console.log("Server running on http://127.0.0.1:3000");
});
验证
- localhost:5500是page1.html
- localhost:5501是page2.html
- 先在5500中访问,一切正常

- 点击"打开page2"访问localhost:5501的page2.html,不出意外的话,打开控制台就会出现CORS错误

当强制刷新5501的page2.html后,会正常显示
解决方案
- 请求后拼接上随机数(适合应急上线,治标不治本)
ts
fetch(`http://127.0.0.1:3000/?random=${Math.random()}`)
- 对于静态资源加上缓存完全没问题,如果是业务请求或者是业务相关的资源,个人觉得最好不要加上响应头去缓存。如果有缓存业务,可以采用JS代码去缓存
- localForage库(本地缓存在localStorage、IndexedDB...)
- MDN Caches 浏览器提供的缓存相关的接口
- 后台配置
Vary: Origin
(未经过测试,理论上协商缓存可行,强缓存不行)
💡 查阅了MDN、stackoverflow、chromeium issue、WHATWG 都没有相关的介绍,如果有明确的来源欢迎评论👏