通过脚本标签与 GET 包含时,JS 文件缓存是不同的
JS file caching is different when included via script tag vs GET
在过去的几天里,我一直陷入缓存地狱,而当我开始了解它时,它仍然有点挣扎。
想要的结果
我想在网站上包含一个 JS 文件并将其缓存 and/or 仅当服务器上的文件已更改时才获取该文件的新副本。我不能在文件名中使用版本标签或散列。文件名需要保持一致。
我在哪里
据我阅读此内容后的理解,使用 Etags 是解决此问题的完美方法。他们将在文件更改时更新,如果标签不匹配,将发送文件的新版本。当我通过浏览器请求文件时这似乎有效
所以你可以看到,在第一次请求时我得到了 200,下载大小为 292 B,在第二次请求中,因为标签匹配,我得到了 304,下载大小为 137 B(我假设只是 header 大小).伟大的! 这正是我想要的。
我的请求 header 寻找 etag:
我的问题
现在这在我从浏览器请求文件时有效,但是在脚本标记中添加 js 文件不会以相同的方式发送请求 headers。因此,打开以下 html 文件
<!DOCTYPE html>
<html>
<body>
<script src="https://myTestSite.com/testCache.js">
</script>
</body>
</html>
我的 js 文件每次都被提取,因为 if-none-match
请求 header 不存在。使用 html 脚本标签时,如何复制在上述场景中观察到的行为?
TL;DR
在使用 html 脚本标签而不是简单的浏览器 GET 请求时,如何使用 Etags 仅请求修改后的 JS 文件?
也许您应该尝试使用 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>
我让它工作了,但并不完全像我预期的那样。这就是我最终要做的。
在我想从中提供我的 js 文件的目录中,我添加了一个 .htaccess 文件
<FilesMatch "\.(js|css)$">
Header set Cache-Control "no-cache, must-revalidate"
</FilesMatch>
我意识到,如果我在本地将我的 js 文件添加到缓存中,它总是会从本地缓存中提取,甚至永远不会向服务器发出请求。因此,即使更改了 Etag,我的客户端也永远不会知道,因为该文件已经在本地缓存了。
所以,我决定完全不缓存文件并重新验证。因此,虽然我确实有轻微的 http headers 开销,但我总是会获得最新的文件,而不需要每次都获取整个文件。
另一个选项(可能更简单)是在资源 URI 的末尾添加一个随机查询字符串:
<script src="https://myTestSite.com/testCache.js?version=<random_value>"></script>
这仍然意味着您正在从服务器获取相同的文件(服务器在返回资源时将忽略查询字符串),因此您不必在后端进行任何更改。
随机值可以是auuid
,这样可以保证随机性。另外,关键可能不一定 version
.
在过去的几天里,我一直陷入缓存地狱,而当我开始了解它时,它仍然有点挣扎。
想要的结果
我想在网站上包含一个 JS 文件并将其缓存 and/or 仅当服务器上的文件已更改时才获取该文件的新副本。我不能在文件名中使用版本标签或散列。文件名需要保持一致。
我在哪里
据我阅读此内容后的理解,使用 Etags 是解决此问题的完美方法。他们将在文件更改时更新,如果标签不匹配,将发送文件的新版本。当我通过浏览器请求文件时这似乎有效
所以你可以看到,在第一次请求时我得到了 200,下载大小为 292 B,在第二次请求中,因为标签匹配,我得到了 304,下载大小为 137 B(我假设只是 header 大小).伟大的! 这正是我想要的。
我的请求 header 寻找 etag:
我的问题
现在这在我从浏览器请求文件时有效,但是在脚本标记中添加 js 文件不会以相同的方式发送请求 headers。因此,打开以下 html 文件
<!DOCTYPE html>
<html>
<body>
<script src="https://myTestSite.com/testCache.js">
</script>
</body>
</html>
我的 js 文件每次都被提取,因为 if-none-match
请求 header 不存在。使用 html 脚本标签时,如何复制在上述场景中观察到的行为?
TL;DR
在使用 html 脚本标签而不是简单的浏览器 GET 请求时,如何使用 Etags 仅请求修改后的 JS 文件?
也许您应该尝试使用 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>
我让它工作了,但并不完全像我预期的那样。这就是我最终要做的。
在我想从中提供我的 js 文件的目录中,我添加了一个 .htaccess 文件
<FilesMatch "\.(js|css)$">
Header set Cache-Control "no-cache, must-revalidate"
</FilesMatch>
我意识到,如果我在本地将我的 js 文件添加到缓存中,它总是会从本地缓存中提取,甚至永远不会向服务器发出请求。因此,即使更改了 Etag,我的客户端也永远不会知道,因为该文件已经在本地缓存了。
所以,我决定完全不缓存文件并重新验证。因此,虽然我确实有轻微的 http headers 开销,但我总是会获得最新的文件,而不需要每次都获取整个文件。
另一个选项(可能更简单)是在资源 URI 的末尾添加一个随机查询字符串:
<script src="https://myTestSite.com/testCache.js?version=<random_value>"></script>
这仍然意味着您正在从服务器获取相同的文件(服务器在返回资源时将忽略查询字符串),因此您不必在后端进行任何更改。
随机值可以是auuid
,这样可以保证随机性。另外,关键可能不一定 version
.