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

检测初始HTML文档缓存来源的JavaScript API查询

检测初始HTML文档缓存来源的JavaScript方案

问题背景

我们需要判断初始HTML文档的来源:浏览器缓存、CDN缓存还是源站。其中CDN缓存和源站可通过CDN返回的server-timing头直接区分,但如何通过JavaScript API检测文档是否直接来自浏览器缓存是核心难点,且需排除依赖开发者工具网络面板的方式。

已验证的无效方法

我们尝试过以下三种方案,但均无法满足需求:

  • 基于transferSize的判断:
    var isCached = performance.getEntriesByType("navigation")[0].transferSize === 0;
    
    该方法在新版Chrome中完全失效,即便文档已被浏览器缓存,也从未返回transferSize === 0的结果,推测仅适用于CSS、JS等非HTML资源。
  • 通过导航类型判断:
    var isCached = window.performance.navigation.type === 2;
    
    navigation.type === 2仅代表后退/前进导航行为,并非文档缓存的可靠指标——例如常规点击链接进入的页面也可能被缓存,但该方法无法识别此类场景。
  • 服务器时间戳对比:
    在文档中嵌入服务器生成的时间戳,前端通过对比当前时间判断是否缓存。但由于我们使用自带缓存的CDN,该方法无法区分文档来自CDN缓存还是浏览器缓存,因此失效。

可行解决方案

方案1:利用导航性能指标的时间差判断

当文档来自浏览器缓存时,浏览器无需向远端发起请求,responseStart与fetchStart的时间差会极小(通常小于1ms)。代码示例:

const navEntry = performance.getEntriesByType("navigation")[0];
// 可根据实际情况调整阈值,建议设为5ms以内
const isBrowserCached = navEntry.responseStart - navEntry.fetchStart < 1;

注意:需排除本地file://协议的开发场景,部分浏览器可能存在微小误差,可适当放宽阈值。

方案2:结合缓存响应头与性能指标验证

先通过时间差初步判断,再验证文档的Cache-Control头是否允许浏览器缓存,进一步确认来源:

async function isFromBrowserCache() {
  const navEntry = performance.getEntriesByType("navigation")[0];
  const timeDiff = navEntry.responseStart - navEntry.fetchStart;
  
  if (timeDiff < 1) {
    // 发起HEAD请求获取缓存策略头
    const response = await fetch(window.location.href, { method: 'HEAD' });
    const cacheControl = response.headers.get('Cache-Control');
    // 判断是否符合浏览器缓存的策略
    return cacheControl?.includes('max-age') || cacheControl?.includes('public') || cacheControl?.includes('private');
  }
  return false;
}

注意:HEAD请求可能触发缓存验证(如携带If-Modified-Since头),需结合实际缓存策略调整逻辑。

方案3:配合CDN标识的多维度推断

利用CDN返回的server-timing头先区分CDN缓存和源站,再通过性能指标推断浏览器缓存:

function detectCacheSource() {
  const navEntry = performance.getEntriesByType("navigation")[0];
  const timeDiff = navEntry.responseStart - navEntry.fetchStart;
  const serverTiming = navEntry.serverTiming;

  // 通过server-timing判断CDN或源站
  const isCDNCached = serverTiming.some(entry => entry.name === 'cache' && entry.description === 'hit');
  const isOrigin = serverTiming.some(entry => entry.name === 'cache' && entry.description === 'miss');
  
  if (isCDNCached) return 'cdn';
  if (isOrigin) return 'origin';
  // 无CDN标识且时间差极小,判定为浏览器缓存
  if (timeDiff < 1) return 'browser';
  return 'unknown';
}

注意:该方案依赖CDN正确配置server-timing头返回缓存状态。


内容的提问来源于stack exchange,提问作者Sven

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:40:44