Html 使用缓存控制的正确方法是什么;“必须重新验证”;关于动态加载的内容?

Html 使用缓存控制的正确方法是什么;“必须重新验证”;关于动态加载的内容?,html,browser-cache,Html,Browser Cache,作为一个背景,我有一个非常大的js文件,它动态加载在一个脚本标记中。客户端会不时更改该文件。如果没有更改,我们不希望重新加载 因此,我浏览了许多关于必须重新验证的stackoverflow文章。 基于此,我实现了如下的缓存头 Cache-Control: must-revalidate,max-age=0 我还启用了ETag。 据我所读和理解,这应该是检查的变化和加载只有当有任何变化 问题是在Firefox和Chrome中,无论是否有更改,文件都会被下载。即使文件和Etag保持不变,浏览器也不

作为一个背景,我有一个非常大的js文件,它动态加载在一个脚本标记中。客户端会不时更改该文件。如果没有更改,我们不希望重新加载

因此,我浏览了许多关于必须重新验证的stackoverflow文章。 基于此,我实现了如下的缓存头

Cache-Control: must-revalidate,max-age=0
我还启用了ETag。 据我所读和理解,这应该是检查的变化和加载只有当有任何变化

问题是在Firefox和Chrome中,无论是否有更改,文件都会被下载。即使文件和Etag保持不变,浏览器也不会从缓存加载

这是怎么回事? 我做错什么了吗? 当我使用“必须重新验证”时,是否应该设置长最大年龄,而不是将最大年龄设置为零

我编辑这个问题是因为我在进一步检查时发现了一些重要的东西。在发布答案之前,请阅读下面的内容

上面描述的这个问题似乎只发生在动态加载的资源上

例如: 如果我在页面源代码中有一个脚本标记

<script src="some-js.js" type="text/javascript">
无论缓存头是什么,都会重新加载此js


知道为什么会发生这种情况吗?

重命名JS文件,使其名称中包含文件的内容哈希,例如:
your_module.489d43f35d9b718c5cdc4f08a7c6c7.JS
并将文件标记为。这样,客户端将只下载文件一次


如果文件内容发生更改,只需根据新内容生成新文件名即可。这种技术通常用于捆绑机。不再需要玩标题了

它每次都会重新加载文件,因为您使用
max age=0停用任何类型的缓存

浏览器可以通过两种方式确认缓存中的文件是否过时:

  • 埃塔格
  • 修改次数
这两种方法都要求浏览器将文件缓存在缓存中,否则无论哪种方法都无法处理该文件。对于要将文件保留在缓存中的浏览器,必须允许其在缓存中保留一段时间。这是通过指定
max age
和/或
Expires
标题来实现的。如果这是
0
,则浏览器不会缓存任何内容。因此,首先允许浏览器通过设置一个正的过期时间来缓存文件

接下来,
must revalidate
指定浏览器必须与服务器检查是否有更新的文件可用。如果有,服务器将发送较新的文件,否则服务器将以HTTP状态代码响应,指示浏览器仍具有最新版本,并且将忽略发送较长的响应正文。要使其工作,必须有一种机制,浏览器和服务器可以使用该机制来确认文件的内容。这就是ETag或修改时间的作用

如果您的服务器为文件设置了
ETag
头,该文件通常包含文件内容的哈希,那么浏览器可以通过请求
(如果没有匹配的
头)对其进行验证。如果文件的ETag仍然匹配,服务器将响应
304 Not Modified

另一种选择是,服务器设置
上次修改的
头,如果自
以来进行了修改,则允许浏览器使用
请求文件,如果文件仍然是最新的,则服务器再次使用
304未修改的
响应


如果没有
必须重新验证
,浏览器只需使用文件的缓存版本,而无需与服务器联系,直到文件的
最长期限
/
过期
时间到达,然后如果没有匹配
/
的文件,如果自
以来进行了修改,浏览器可能会再次使用
请求该文件。使用
must revalidate
指令,每次使用缓存文件之前,都会指示浏览器与服务器签入。

我认为这不是最大年龄的问题。在问题中查看我的新编辑(我在您发布此内容后添加)。如果max age出现问题,则具有相同缓存头的其他资源也会重新加载,但此问题仅发生在动态加载的资源中。
var s = document.createElement('script');
s.setAttribute('src', 'newjs.js');
s.setAttribute('id', 'script1');
s.type = 'text/javascript';
s.async = false;
s.onerror = errorcallback;
s.onload = loadcallback;
document.body.appendChild(s);