2014-07-07 16 views
7

假設我們有幾個不同的網站:website1.com,website2.com,website3.com。我們在所有這些應用程序上使用jQuery,並將其包含在CDN中,如googleapis.com。瀏覽器的預期行爲是緩存一次,並將其用於所有其他網站。 Chrome似乎這樣做,但Safari爲每個域下載jQuery。Safari不會緩存跨不同域的資源

  1. 隨着鉻下面開放nytimes.combbc.comdw.de給定的JS代碼。
  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爲每個新域獲取圖像(但不是子域)。

+0

我不確定我會相信這樣的測試,你手動注入jQuery。瀏覽器可能會處理這些不同於頁面本身包含的頁面。 – ceejayoz

+0

@ceejayoz如果它會是js代碼,異步追加jQuery?這個通過DevTools追加的內容不應該有任何不同。 –

+0

如果緩存有時在通過webdev工具進行操作時被繞過,那對我來說就不足爲奇了。我建議在將其視爲問題之前消除潛在的原因。你甚至可以在StackExchange網絡上測試它 - 去幾個站點,看看共享的靜態資產是否跨域緩存。 – ceejayoz

回答

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'); 
})(); 

注:Safari瀏覽器已經與過去緩存的一些問題。然而,據我所知,這主要是爲了陳舊的內容 - 而不是相反。

-1

以下是一些建議:

  1. 如果「禁用緩存」選項被禁用,你檢查?
  2. 您是否在網絡開發面板中查找HTTP狀態碼?
  3. 您是否嘗試過使用WireShark這類工具捕獲流量?

此致敬禮。

+0

您正在測試哪個操作系統? – kewwwa

0

我也注意到了這一點,我懷疑這是出於隱私原因。

默認情況下,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放在該框中,以便僅通過a.com將其發送到b.com以獲取更多請求。對於c.com的請求,它不會被髮送到b.com

現在輸入緩存,特別是Etag標題。 Etag是一個任意字符串(通常是文件的散列),可用於確定請求的資源是否自該用戶請求最後一次請求後發生了更改。這通常是一件好事。它保存重新發送整個文件,如果它沒有改變。

但是,因爲Etag任意字符串,所以b.com可以將其設置爲包含客戶端ID。這叫做Etag tracking。它允許跨域跟蹤一個人,幾乎完全相同的方式做餅乾。


摘要:通過不跨域共享緩存,Safari瀏覽器保護你從跨域的Etag跟蹤。

+0

這應該是一個被接受的答案。只是增加了一點點 – ffeast