跨域预获取脚本后如何从浏览器缓存加载?
这个问题我做项目时也踩过同款坑——跨域预取的资源明明在着陆页加载了,跳转主应用后却还是重新请求,核心原因大多和浏览器的缓存隔离机制、资源的缓存配置有关。咱们一步步来拆解解决:
1. 给预取标签加上crossorigin属性
浏览器对跨域预取的资源有默认缓存隔离策略,哪怕目标域名是资源的同源站,也得明确声明允许跨域访问才能复用缓存。把你的预取代码改成这样:
<link rel="prefetch" href="https://bookings.test.com/vendor.js" as="script" crossorigin="anonymous">
这里的crossorigin="anonymous"告诉浏览器:这个资源允许跨域预取,后续同源的bookings.test.com页面可以访问它的缓存。如果你的vendor.js需要携带凭证(比如Cookie),就改成crossorigin="use-credentials",同时要确保服务器的CORS配置允许对应的凭证传递。
2. 确保资源的缓存头配置合理
就算预取成功了,如果服务器返回的vendor.js没有正确的缓存策略,浏览器只会把它存在临时缓存里,跳转后直接丢弃。让后端团队检查bookings.test.com/vendor.js的响应头,必须包含:
Cache-Control: public, max-age=31536000, immutable
public:允许所有上下文(包括跨域预取的页面)访问这个缓存max-age=31536000:设置1年的缓存有效期(可根据业务调整时长)immutable:告诉浏览器这个资源不会变更,不用再发ETag/Last-Modified这类验证请求
如果缓存头是private或者no-cache,浏览器不会把预取资源存入长期HTTP缓存,这是最常见的问题根源之一。
3. 验证资源URL的完全一致性
浏览器的缓存是严格匹配URL的,哪怕一个字符不同都会被当成新资源。要确保:
- 着陆页预取的URL和主应用请求的URL完全一致(包括协议、域名、路径、查询参数,比如有没有
?v=1.0这类版本号) - 主应用里的脚本引用路径解析后和预取URL一致,比如主应用用相对路径
/vendor.js,要确认它解析后就是https://bookings.test.com/vendor.js
4. 用DevTools调试缓存命中情况
打开Chrome DevTools的「Network」面板,做以下检查:
- 取消勾选「Disable cache」(一定要关掉,否则看不到真实缓存行为)
- 着陆页加载时,找到预取的
vendor.js,看「Size」列:显示prefetch cache说明资源在预取缓存里;显示disk cache/memory cache说明已存入HTTP缓存 - 跳转至bookings.test.com后,查看
vendor.js的「Size」列:如果显示from disk cache/from memory cache,说明缓存复用成功;如果还是200 OK,就得回头检查前面的配置
总结
最关键的两个修复点是给预取标签加crossorigin属性和配置正确的Cache-Control头,这两个搞定后,大部分跨域预取缓存复用的问题都能解决。如果还是不行,再检查URL一致性和SRI(如果主应用用了资源完整性校验,预取资源的哈希必须和主应用的integrity属性匹配)。
内容的提问来源于stack exchange,提问作者CaspianTerrazzo

