【问题标题】:Safari doesn't cache resources across different domainsSafari 不会跨不同域缓存资源
【发布时间】:2014-08-28 06:59:55
【问题描述】:

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

例子

  1. 使用下面给定的 JS 代码在 Chrome 中打开 nytimes.combbc.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);

UPD:使用静态图像对其进行了测试。

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

【问题讨论】:

  • 我不确定我是否会信任像这样手动注入 jQuery 的测试。浏览器可能会以不同于页面本身包含的方式处理这些内容。
  • @ceejayoz 如果是异步附加 jQuery 的 js 代码会怎样?通过 DevTools 进行的这种附加应该没有什么不同。
  • 如果在通过 webdev 工具操作时有时会绕过缓存,这对我来说并不奇怪。我建议在假设它是一个问题之前消除该潜在原因。您甚至可以在 StackExchange 网络上对其进行测试 - 访问几个站点并查看共享的静态资产是否跨域缓存。
  • 我使用本地域和真正的“脚本”标签进行了快速测试。它适用于 test1.localtest.me、test2.localtest.me 等子域,但会中断 localhost 或 127.0.0.1,即使它们要求相同的资源
  • 如果浏览器处理 127.0.0.1/localhost 的方式不同,我不会感到惊讶。

标签: caching safari browser-cache cdn google-cdn


【解决方案1】:

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

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

【讨论】:

【解决方案2】:

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

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

Safari 会阻止这种行为。如果b.coma.com 请求的资源设置了一个cookie,Safari 会将该cookie 装箱,因此它只会发送到b.com 以获取a.com 的更多请求。对于c.com 的请求,它不会发送到b.com

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

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


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

【讨论】:

  • 这应该是一个可以接受的答案。只是增强了一点
  • @feast 如果您觉得足以发表评论,为什么不投票支持答案?
【解决方案3】:

以下是一些建议:

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

最好的问候。

【讨论】:

  • 你在哪个操作系统上测试?
【解决方案4】:

您可以尝试使用 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 过去曾遇到过一些缓存问题。然而,据我了解,这主要是关于提供陈旧的内容——而不是相反。

【讨论】:

    猜你喜欢
    • 2012-06-30
    • 2017-07-13
    • 2019-09-19
    • 2012-05-28
    • 2013-02-09
    • 2017-04-04
    • 2014-05-12
    • 1970-01-01
    • 2013-01-18
    相关资源
    最近更新 更多