Safari 浏览器不会跨不同域缓存资源



假设我们有几个不同的网站:website1.com, website2.com, website3.com。我们在所有这些网站上使用jQuery,并从CDN(如googleapis.com)中包含它。浏览器的预期行为将是缓存它一次,并将其用于所有其他网站。Chrome似乎可以做到这一点,但Safari为每个域名下载jQuery。

例子
  1. 与给定的JS代码下面打开nytimes.com, bbc.com和dw.de Chrome浏览器
  2. 在第一个网站上添加jQuery,然后查看DevTools的Network选项卡。它会说它得到了jQuery。
  3. 现在打开任何其他网站并再次添加jQuery -答案将是" from cache "

然而,Safari会说它正在为每个域名加载jQuery,但尝试打开其中一个域名上的任何网页并再次添加脚本-你会看到现在它说它从缓存中获取了jQuery。所以它看起来像是缓存了一个域的数据,即使它已经从另一个域的确切URL下载了一个资源。

这个假设是正确的,如果是,如何修复它?

可以复制/粘贴的代码:

setTimeout(function() {
    var SCRIPT_SRC = '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js';
    var s = document.createElement('script');
    s.type = 'text/javascript';
    s.async = true;
    s.src = SCRIPT_SRC;
    var x = document.getElementsByTagName('script')[0];
    x.parentNode.insertBefore(s, x);
}, 0);

UPD: test it with a static image.

test.com、test2.com和test3.com有<img src="http://image.com/image.jpg" />。在除Safari之外的所有浏览器中,访问日志只显示对图像的一次首次请求。Safari获取每个新域(但不是子域)的图像。

我也注意到了这一点,我怀疑这是出于隐私原因。

默认情况下,Safari会阻止第三方cookie。第三方cookie是a.com请求的资源在b.com上设置的cookie。例如,这可以用于跟踪跨域的人员。您可以在a.comc.com请求的b.com上拥有一个脚本。b.com可以根据第三方cookie在这个脚本中插入一个唯一的客户端ID,这样a.comc.com就可以跟踪到这是同一个人。

Safari阻止此行为。如果b.coma.com请求的资源设置了cookie, Safari会将该cookie框起来,以便a.com请求更多的资源时才将其发送给b.com。对于c.com的请求,它不会发送给b.com

现在输入缓存,特别是Etag头。Etag是一个任意字符串(通常是文件的散列),可用于确定所请求的资源自上次请求以来是否发生了更改。这通常是一件好事。

如果没有更改,则可以节省重新发送整个文件。

然而,因为Etag是一个任意字符串,b.com可以设置它包含一个客户端ID。这叫做Etag跟踪。它允许跨域跟踪一个人,其方式几乎与cookie完全相同。


摘要:通过不跨域共享缓存,Safari保护您免受跨域Etag跟踪。

这是经过设计的,Safari团队称之为智能跟踪保护- https://webkit.org/blog/7675/intelligent-tracking-prevention/-缓存是基于文档来源和第三方来源的双密钥

基于对HTTP存档数据的研究和雅虎/Facebook对缓存生命周期的研究,我怀疑jQuery等共享缓存是否有效-没有足够的网站使用相同版本的库,库不会在缓存中存活很长时间-所以Safari的行为有助于防止跟踪,而不是真正影响性能

您可以尝试使用XMLHTTPRequest,而不是简单地添加DOM元素。它允许您定义自定义头——其中之一是Cache-Control

试一试,它应该会覆盖浏览器层面上发生的任何事情:

(function () {
    var newRequest = function() {
        return (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject( 'MsXml2.XmlHttp' );
    }
    var loadScript = function(url) {
        var http = new newRequest();
        http.onReadyStateChange = function() {
            if (http.readyState === 4) {
                if (http.status === 200 || http.status === 304) {
                    appendToPage(http.responseText);
                }
            }
        }
        // This is where you set your cache
        http.setRequestHeader( 'Cache-Control', 'max-age=0' )// <-- change this to a value larger than 0
        http.open('GET', url, true);
        http.send(null);
    }
    var appendToPage = function(source) {
        if (source === null) return false;
        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');
            script.language = 'javascript';
            script.type  = 'text/javascript';
            script.defer = true;
            script.text  = source;
        head.appendChild(script);
    }
    loadScript( '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js' );
})();

注意:Safari过去在缓存方面有一些问题。然而,据我所知,这主要是为了提供过时的内容,而不是相反。

以下是一些建议:

  1. 你是否检查了"禁用缓存"选项是否被禁用?
  2. 您是否在网络开发面板中查找HTTP状态码?
  3. 您是否尝试过使用WireShark等工具捕获流量?

问好。

相关内容

  • 没有找到相关文章

最新更新