如何使用 JavaScript 来检测我是否在缓存的页面上

How can I use JavaScript to detect if I am on a cached page

提问人:Jamey McElveen 提问时间:11/4/2008 更新时间:6/1/2023 访问量:17911

问:

我想长时间从缓存中显示,并且我希望页面呈现与从缓存加载页面的行为略有不同。有没有一种简单的方法可以用 JavaScript 确定这一点?

JavaScript的

评论


答:

15赞 Daniel 11/4/2008 #1

一种方法是在页面中包含页面的生成时间,然后使用一些 javascript 将本地时间与页面生成时间进行比较。如果时间相差一个阈值,则页面来自缓存。问题在于,如果客户端计算机的时间设置不正确,尽管您可以通过让客户端在生成页面的请求中包含其当前系统时间,然后将该值发送回客户端来解决这个问题。

评论

0赞 Bogdan 11/4/2008
该死的,你把我打败了,竖起大拇指!
0赞 Jamey McElveen 11/4/2008
我实际上在考虑这个解决方案。我希望文档中有一些更容易的东西,但也许它不存在:)
1赞 Chad M 11/4/2016
如果您正在寻找它以任何一致性工作,这不是一个好的答案。在慢加载时间、服务器本地时间与客户端本地时间之间,或者系统日期不正确的客户端之间,您无法保证该测试的真实性。
1赞 Will Dieterich 11/4/2008 #2

不是直接的,某些浏览器可能有一些自定义命令。

有一种解决方法可以满足您的要求。使用 cookie 存储第一次访问,然后使用 META HTTP-EQUIV 设置文件缓存的时间长度 ()。如果当前时间在从 到 的时间段内,则将其视为从缓存加载。缓存过期后,重置 cookie 时间。timestampcacheLengthtimestamptimestamp+cacheLength

2赞 Allain Lalonde 11/4/2008 #3

使用 XmlHttpRequest,可以拉出当前页面,然后检查响应的 http 标头。

最好的情况是只执行 HEAD 请求,然后检查标头。

有关执行此操作的一些示例,请查看 http://www.jibbering.com/2002/4/httprequest.html

评论

0赞 Heat Miser 11/4/2008
我正要提出同样的建议,但问题表明他想查看当前加载的页面是否被缓存,如果您触发 XHR,那么这将表明下一个请求,而不是当前请求。
0赞 Jamey McElveen 11/4/2008
谢谢,我不能使用它,但是,您发送给我的链接可以帮助我解决另一个问题。
20赞 Jamey McElveen 11/5/2008 #4

我从上面给出的答案“丹尼尔”开始,但我担心在缓慢的连接中,我可能会遇到一些延迟问题。

这是最终对我有用的解决方案。在服务器端,我添加了一个 cookie refCount 并将其值设置为 0。在 javascript 中加载文档时,我首先检查 refCount,然后递增它。当检查 refCount 是否大于 1 时,我知道页面已缓存。所以对于这个来说,这就像一个魅力。

谢谢你们引导我找到这个解决方案。

评论

6赞 Karl 2/12/2010
我自己也用过同样的方法。我在我的博客上写了一个详细的描述:monket.net/blog/2010/02/......
1赞 Sergei Tachenov 8/28/2019
拯救了我的一天!不过,我不明白为什么要增加 cookie。只需将其设置为“firstLoad=yes”,并在 中更改为“firstLoad=no”。从本质上讲,cookie 只是一个布尔标志,它会永久保留,直到页面实际重新加载。onLoad
4赞 Reactgular 11/15/2012 #5

虽然这个问题已经有 4 年了。我以为我会使用 jQuery 和 History 插件添加我的 2 美分。

$(document).ready(function()
{
    $('body').append('<div class="is_cached"></div>');
});

History.Adapter.bind(window,'statechange',function(){
   if($('.is_cached').length >= 1)
   {
      alert('this page is cached');
   }
});

首次加载文档时。将附加一个新div.is_cached。加载缓存页面时,没有兼容的方法来执行 javascript,但您可以监视历史记录更改。当历史记录更改且div.is_cached存在时,用户正在查看缓存的分页。

评论

0赞 Naveen Gamage 11/29/2012
我应该使用哪些 javascript 文件来测试它?我下载了历史插件,但它有很多JS文件......哪一个在处理这个?
0赞 Reactgular 11/30/2012
我在jQuery中使用了这个,没有任何问题。github.com/balupton/history.js/blob/master/scripts/bundled/......
0赞 Reactgular 11/30/2012
注意:IF 语句应为 >= 1
0赞 Naveen Gamage 11/30/2012
我试过了,但什么也没发生,我链接了历史js和最新的jqeury js......请检查 - slgag.com/cd.html
0赞 Reactgular 11/30/2012
您缺少 <script> 标记的脚本类型。
12赞 Knaģis 8/13/2018 #6

使用新的资源计时级别 2 规范,可以使用 transfer size 属性来检查页面是否从缓存加载:

var isCached = performance.getEntriesByType("navigation")[0].transferSize === 0;

评论

0赞 andrew.creamentas 3/16/2020
在我的情况下,对于 firefox 74 win10,条件应该是 ,否则会永久重新加载。pnt.transferSize === 0 && pnt.type === 'back_forward'
1赞 Afterparty 5/22/2019 #7
  1. 在创建时将唯一数据添加到服务器上的页面。例如,随机数或创建时间:
       window.rand = {{ rand() }} 
  1. 使用本地存储将 url 与数字一起保存,并在需要时稍后进行比较:
       reloadIfCached() {
            var cached = localStorage.getItem(window.location.href) == window.rand;
            if (cached) {
                window.location.reload();
            }
            localStorage.setItem(window.location.href, window.rand);
       }
1赞 Junior Tour 6/1/2023 #8

尝试 API,它将返回所有网络资源的每个阶段时间及其 ,如下所示:performance.getEntriesByType('resource')nametype

enter image description here

上面的屏幕截图显示,我们得到的文件名为 download total 是 925 (ms),它的类型是 .https://www.google.com/xjs/_/js/k=xjs...durationscript

因此,我们可以根据其 来检测某些文件是否命中缓存,并进行过滤,或者我们想要关注:durationtypename

const includeFileTypes = [
  'script',
  // 'css',
  // 'img',
]
const includeFileNames = [
  'yourTargteFileName.js',
]

function getFileNameFromURL(url) {
  return url?.match(/[^\\/]+(?!.*\/)/)?.[0]
}

const getResourceTiming = () => {
  const resources = performance
    .getEntriesByType('resource')
    .filter(({ initiatorType }) => {
      return includeFileTypes.includes(initiatorType)
    })
    // .filter(({ name }) => {
    //   return includeFileNames.includes(getFileNameFromURL(name))
    // });
  return resources.map(
    ({
      name,
      // redirectEnd,
      // redirectStart,
      // domainLookupEnd,
      // domainLookupStart,
      // connectEnd,
      // connectStart,
      // secureConnectionStart,
      responseEnd,
      responseStart,
      // fetchStart,
      // requestStart,
      startTime,
      duration,
    }) => ({
      name: getFileNameFromURL(name),
      startTime: parseInt(startTime),
      endTime: parseInt(responseEnd - responseStart),
      duration: parseInt(duration),
    }),
  );
};

function getHitCacheFiles(allTargetResources) {
  return allTargetResources?.filter(({name, duration}) => {
    if (duration < 20) {
      console.log(`Hit Cache: ${name}`)
      return true
    } else {
      console.log(`Not Hit Cache: ${name}`)
      return false
    }
  })
}


const allTargetResources = getResourceTiming()

console.table(getHitCacheFiles(allTargetResources))

演示

它将打印:

enter image description here

它还与 DevTool Network 面板保持一致:

enter image description here

getEntriesByType('resource')用法比 简单,它不需要额外的 HTTP 头transferSizeTiming-Allow-Origin: https://yoursite.com

参考资料:transferSize#cross-origin_content_size_information