使浏览器重新验证(但不一定重新获取)图像

Cause browser to revalidate (but not necessarily refetch) an image

本文关键字:新获取 获取 图像 不一定 验证 浏览器 新验证      更新时间:2023-09-26

在我的网络应用程序中,我们提供所有带有HTTP缓存标头的图像,有效期为24小时,还有ETags。但有时 Javascript 客户端应用程序有理由怀疑图像可能已更新。在这些情况下,我想强制浏览器重新验证图像缓存,而不会实际破坏缓存。

例如,我得到一个用户记录(以 JSON 格式),上面有一个最近的上次更新日期。LastUpdated 日期可能更改的原因有多种:用户可能更改了昵称、加入了新讨论区或更改了图像。因此,图像很有可能没有更改,但我们需要检查。

我知道我可以在 URL 后附加缓存断开器的情况下重新请求图像。但这会强制图像重新加载,无论它是否已更改,导致浏览器缓存中有两个条目,并迫使我使用新 url 更新所有图像。我真正想要的是让浏览器重新请求相同的URL,并在请求中发送适当的If-None-Match和/或If-Modified-Since标头,以便在图像没有更改时它将获得304。

有什么方法可以在Javascript中做到这一点吗?

由于图像位于服务器中,因此在缓存中,服务器是需要进行查询的位置。我会在页面加载之前进行检查,如果需要,强制服务器更新缓存中的特定图像。"HTML"部分应始终假设所有 img 标签等都是正确的。

更新服务器缓存中单个文件的最佳方法是IMO的不同野兽。

这实际上很容易完成。 对Cache-Control标头设置为 max-age=0 的映像发出 AJAX 请求。

服务器必须使用更新的图像(和一组新的缓存标头)或包含Cache-Control标头(public, max-age=123)的 304 进行响应。

带有 Cache-Control 标头的 304 非常重要,因为它指示浏览器更新与资源关联的新鲜度信息。

请求完成后,从 DOM 中删除旧的 <img> 元素,然后重新插入指向同一src的新元素。

这是有效的,因为请求Cache-Control标头告诉浏览器忽略其缓存并转到网络。 当浏览器收到响应时,它会更新其缓存 - 即使您实际上没有对 AJAX 结果执行任何操作。

现在,当您删除旧元素并插入新元素时,浏览器会直接从其缓存中获取最近更新的图像。

在 Chrome 的网络检查器中,您会看到两个请求:AJAX 请求,然后是通过重新插入 <img> 元素生成的请求。 但是,如果服务器正确设置了Cache-Control标头,则第二个"请求"将由浏览器的缓存完成,并且实际上不会通过网络发送任何内容。

function updateImage(el) {
    el = $(el);
    var src = el.attr('src');
    $.ajax({
        url: src,
        headers: {
            'Cache-Control': 'max-age=0'
        },
        success: function() {
            var parent = el.parent(); 
            el.remove();
            // this assumes that the <img> has no siblings and no attributes/classes/etc...
            parent.append('<img>').attr('src',src);
        }
    });
}