Safari不会跨不同域缓存资源

Dan*_*J F 7 safari caching cdn browser-cache google-cdn

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

  1. 使用下面给出的JS代码在Chrome 中打开nytimes.com,bbc.comdw.de.
  2. 在第一个网站上添加jQuery,然后查看DevTools的Network选项卡.它会说它有jQuery.
  3. 现在打开任何其他网站并再次附加jQuery - 答案将是"来自缓存".

但是,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);
Run Code Online (Sandbox Code Playgroud)

UPD:用静态图像测试它.

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

cho*_*wey 5

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

默认情况下,Safari 会阻止第三方 cookie。第三方 cookie 是b.com为 请求的资源设置的 cookie a.com。例如,这可用于跨域跟踪人员。您可以使用和b.com请求的脚本。可以基于第三方 cookie 将唯一的客户端 ID 插入到此脚本中,以便并且可以跟踪这是同一个人。a.comc.comb.coma.comc.com

Safari 会阻止这种行为。如果b.com设置为所要求的资源一个cookie a.com,Safari会盒该cookie,因此只发送到b.com由更多的请求a.com。它不会被发送到b.com请求c.com

现在输入缓存,特别是Etag标题。AnEtag是一个任意字符串(通常是文件的哈希值),可用于确定所请求的资源自上次请求以来是否已更改。这通常是一件好事。如果它没有改变,它会保存重新发送整个文件。

但是,由于 anEtag任意字符串,因此b.com可以将其设置为包含客户端 ID。这称为Etag 跟踪。它允许以与 cookie 几乎完全相同的方式跨域跟踪一个人。


简介:通过不跨域共享缓存,Safari 可以保护您免受跨域 Etag 跟踪。


der*_*lwc 0

您可以尝试使用 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' );
})();
Run Code Online (Sandbox Code Playgroud)

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