为什么浏览器不尊重Cache-Control标头来加载`(new Image())。src = ...`的图像? [英] Why don't browsers respect Cache-Control headers for images loaded with `(new Image()).src = ...`?
问题描述
测试用例:
<script>
console.log('request');
(new Image()).src = 'https://s3.amazonaws.com/mapbox-gl-js/tests/no-cache.png';
setInterval(function() {
console.log('request');
(new Image()).src = 'https://s3.amazonaws.com/mapbox-gl-js/tests/no-cache.png';
}, 5000);
</script>
Chrome和Firefox都不会对 no-cache.png
,尽管已与 Cache-Control:no-cache
一起使用,表示用户代理必须重新验证缓存内容。
Neither Chrome nor Firefox make any network requests for no-cache.png
beyond the first, despite it being served with Cache-Control: no-cache
, indicating that user agents must revalidate cached content.
此处的几个问题(例如,)对此进行说明并提供解决方法,但我最想回答更基本的问题:
A few questions here (e.g. this one) touch on this and provide workarounds, but I'm most interested in answering more fundamental questions:
- 哪些网络规范(如果有的话)允许或要求这种行为?
- 如果未指定,至少由一个或多个浏览器正式记录?
- 网络作者对此行为有什么控制措施?
- 尤其是,有没有办法破坏缓存而不会丢失通过
If-None-Match
重新验证的好处,就像使用缓存无效化查询参数一样?
- What web specifications, if any, permit or require this behavior?
- If it is not specified, is it at least officially documented by one or more browsers?
- What controls, if any, do web authors have over this behavior?
- In particular, is there a way to bust the cache without losing the benefits of revalidation via
If-None-Match
, as the use of a cache-busting query parameter does?
推荐答案
图像的特殊行为在 HTML标准:
每个
Document
对象必须具有可用图像列表。此列表中的每个图像都由一个元组标识,该元组包含绝对URL,CORS设置属性模式,以及如果该模式不是No CORS,则为原点。每个图像还有一个忽略高层缓存标志。
Each
Document
object must have a list of available images. Each image in this list is identified by a tuple consisting of an absolute URL, a CORS settings attribute mode, and, if the mode is not No CORS, an origin. Each image furthermore has an ignore higher-layer caching flag.
此标志控制是否用户代理从可用图像列表中删除一个条目,或者从资源的高层缓存语义未指定的条目中删除该条目(例如HTTP Cache-Control
响应标头)。
It is this flag that controls whether a user agent removes an entry from the list of available images or not given higher-layer caching semantics for the resource (e.g. the HTTP Cache-Control
response header).
标志已设置 ,并且在完成加载图像源的网络任务时,该图像已添加到可用图像列表中。
The flag is set and the image added to the list of available images when the networking task to load an image source completes.
根据此评论在询问此行为的Chromium错误中, Cache-Control:无存储
将在Chrome中覆盖此行为,但这可能会更改。
According to this comment on a Chromium bug inquiring about this behavior, Cache-Control: no-store
will override this behavior in Chrome, but this is subject to change.
除了 Cache-Control:no-store
或在URL上附加一个缓存无效查询参数,这也会通过<$ c禁用重新验证$ c> If-None-Match ,我知道b的另一种方式跳过忽略高级缓存标志:通过 XMLHttpRequest
设置 xhr.responseType ='arraybuffer'
加载图像数据,使用响应数据创建一个 Blob
对象,然后将该Blob加载到具有 Image
> createObjectURL :
Besides Cache-Control: no-store
or appending a cache-busting query parameter to the URL, which also disables revalidation via If-None-Match
, I know of one other way of bypassing the ignore higher-level caching flag: load the image data via XMLHttpRequest
, setting xhr.responseType = 'arraybuffer'
, create a Blob
object with the response data, and then load the blob into an Image
with createObjectURL
:
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
var img = new Image();
img.onload = function() {
// ... do something with img
URL.revokeObjectURL(img.src);
};
var blob = new Blob([new Uint8Array(xhr.response)], { type: 'image/png' });
img.src = URL.createObjectURL(blob);
};
xhr.send();
这篇关于为什么浏览器不尊重Cache-Control标头来加载`(new Image())。src = ...`的图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!