You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

已配置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 00:35:20