在过去的几天里,我一直在缓存地狱,而我开始变得有点挣扎。
所需结果
我想在网站上包含一个JS文件,并对其进行缓存和/或仅在服务器上更改了文件时才获取该文件的新副本。我不能在文件名中使用版本标记或哈希。文件名需要保持一致。
我在哪里
根据我的理解,使用Etags进行阅读后,这是一个完美的解决方案。它们将在文件更改时更新,并且如果标签不匹配,则会发送文件的新版本。当我通过浏览器请求文件时,这似乎可行
因此您可以看到,在第一个请求上我得到200,下载大小为292 B,在第二个请求上,因为标签匹配,我得到304,下载大小为137 B(我假设只是标头大小)。大! 这正是我想要的。
我的问题
现在,当我从浏览器请求文件时,此方法有效,但是在脚本标签中添加js文件不会以相同的方式发送请求标头。因此,打开以下html文件
<!DOCTYPE html>
<html>
<body>
<script src="https://myTestSite.com/testCache.js">
</script>
</body>
</html>
因为if-none-match
请求标头不存在,所以每次都提取我的js文件。当使用html脚本标记时,如何复制在上述情况下观察到的行为?
TL; DR
在使用html脚本标签而不是简单的浏览器GET请求时,如何使用Etags仅请求修改的JS文件?
答案 0 :(得分:1)
另一个选择(也许更简单)是在资源URI的末尾添加一个随机查询字符串:
<script src="https://myTestSite.com/testCache.js?version=<random_value>"></script>
这仍然意味着您正在从服务器获取相同的文件(服务器在返回资源时将忽略查询字符串),因此您不必在后端进行任何更改。
随机值可以是uuid
,这将确保随机性。密钥也可能不需要version
。
答案 1 :(得分:0)
也许您应该尝试使用MLHttpRequest下载文件:
<!DOCTYPE html>
<html>
<body>
<script>
(() => {
var xhr = new XMLHttpRequest();
xhr.open('GET', "https://myTestSite.com/testCache.js");
xhr.setRequestHeader('if-modified-since', '/*...*/')
xhr.setRequestHeader('if-none-match', '/*...*/')
//add more headers if you need
xhr.onreadystatechange = function(){
if(this.readyState == 4){
if(this.status == 200){
//succeed
}else{
//failed
}
}
},
xhr.send();
})()
</script>
</body>
</html>
答案 2 :(得分:0)
我得到了它,但是并没有完全按照我的预期工作。这就是我最终要做的。
在我要提供js文件的目录中,添加了.htaccess文件
<FilesMatch "\.(js|css)$">
Header set Cache-Control "no-cache, must-revalidate"
</FilesMatch>
我意识到,如果我将js文件本地添加到缓存中,它将始终从本地缓存中拉出,甚至从不向服务器发出请求。因此,即使Etag已更改,我的客户端也永远不会知道,因为该文件已在本地缓存。
因此,我决定完全不缓存文件并重新验证。因此,尽管我确实有一些HTTP标头的开销,但我将始终获得最新文件,而不必每次都提取整个文件。