已配置Cache-Control仍随机加载JS/CSS:浏览器缓存异常问询
浏览器缓存JS/CSS文件的额外影响因素
我已在Nginx配置文件中成功为JS/CSS文件设置了Cache-Control头,配置如下:
location ~* \.(css|js)$ { add_header Pragma public; add_header Cache-Control "public, must-revalidate, proxy-revalidate, max-age=305360000, s-maxage=305360000"; }
但页面刷新时,JS/CSS文件会随机从缓存或服务器加载。除了Cache-Control头外,还有哪些因素决定浏览器从缓存加载文件?
文件从缓存加载时的请求头
Provisional headers are shown. Disable cache to see full headers. Learn more Referer: https://hacdomain/login/?next=%2Fui%2F%23%2Fdashboard sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
文件从缓存加载时的响应头
c-trace: a37def20-1192-48e2-8664-6b819d7d768f cache-control: public, must-revalidate, proxy-revalidate, max-age=305360000, s-maxage=305360000 content-encoding: gzip content-security-policy: default-src 'self' data: mediastream: blob: filesystem: 'unsafe-inline' 'unsafe-eval' content-type: application/javascript; charset=utf-8 date: Wed, 14 Dec 2022 07:50:34 GMT etag: W/"62db1945-6ecb68" last-modified: Fri, 22 Jul 2022 21:40:21 GMT pragma: public referrer-policy: same-origin strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked vary: Accept-Encoding x-content-type-options: nosniff x-frame-options: SAMEORIGIN x-xss-protection: 1
请求发送到服务器时的请求头
Accept: text/css,*/*;q=0.1 Accept-Encoding: gzip, deflate, br Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,hi;q=0.7 Connection: keep-alive Cookie: watcher.session_id=MTY3MTAwMzE2MHxOd3dBTkZBMFdFODNVMVZHV1ZoRVVVWllRVFpXV0VWRFIwMU5XVmRUUkVkWlRFdFRNMFkyVFVkSU4wdE5OMWsxVEZGV1FVZEVUMEU9fPRrNkIO81Pe0pho9cQJCkXH3cPrpYFumxaPLZdT1snG Host: hacdomain Referer: https://hacdomain/login/?next=%2Fui%2F%23%2Fdashboard sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Sec-Fetch-Dest: style Sec-Fetch-Mode: no-cors Sec-Fetch-Site: same-origin User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
请求由服务器处理时的响应头
c-trace: 3880cc51-32a0-477c-aac1-63d60107062f cache-control: public, must-revalidate, proxy-revalidate, max-age=305360000, s-maxage=305360000 content-encoding: gzip content-security-policy: default-src 'self' data: mediastream: blob: filesystem: 'unsafe-inline' 'unsafe-eval' content-type: text/css date: Wed, 14 Dec 2022 07:51:40 GMT etag: W/"62db1945-37f0f" last-modified: Fri, 22 Jul 2022 21:40:21 GMT pragma: public referrer-policy: same-origin strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked vary: Accept-Encoding x-content-type-options: nosniff x-frame-options: SAMEORIGIN x-xss-protection: 1
除Cache-Control外的关键影响因素:
- ETag与缓存验证机制:响应头中的
ETag字段会让浏览器在缓存有效期内(或刷新页面时)发送If-None-Match请求头验证资源是否变更。如果服务器返回304状态码,浏览器复用缓存;若ETag不匹配则重新下载。部分场景下浏览器可能跳过验证直接使用缓存,导致加载行为差异。 - Last-Modified与If-Modified-Since:响应头的
Last-Modified记录了资源最后修改时间,浏览器会通过If-Modified-Since请求头询问服务器资源是否更新。若资源未修改,服务器返回304,浏览器使用缓存。 - Vary头的缓存区分规则:你的响应头包含
Vary: Accept-Encoding,这意味着缓存会根据请求头的Accept-Encoding值区分存储。如果某次请求的Accept-Encoding与缓存时的不一致(比如缓存是gzip,请求包含br编码),浏览器会重新向服务器请求资源。 - 浏览器刷新行为的差异:普通刷新(F5)会触发缓存验证,而地址栏回车或页面内跳转可能直接使用缓存;强制刷新(Ctrl+F5)则会忽略缓存直接请求服务器。如果用户的刷新操作不固定,就会出现随机加载的情况。
- 请求的Fetch模式与目的:发送到服务器的请求带有
Sec-Fetch-Dest: style和Sec-Fetch-Mode: no-cors,某些Fetch模式下浏览器的缓存策略会调整,比如no-cors模式可能限制缓存复用的条件。 - Cookie的影响:虽然你的Cache-Control设置为
public(允许缓存带Cookie的请求),但部分浏览器对带Cookie的资源缓存策略更严格,可能会优先重新请求而非复用缓存。对比你的请求头,发送到服务器的请求带有Cookie,而缓存加载的请求未显示Cookie字段,这可能是触发差异的原因之一。 - 浏览器缓存空间限制:当浏览器缓存存储空间不足时,会自动清理较旧的缓存文件,导致被清理的资源需要重新从服务器加载。
内容的提问来源于stack exchange,提问作者Saurabh Batra
相关产品推荐
相关产品推荐

