2012-04-20 63 views
48

我和我的朋友正在研究一個網站,我們希望緩存某些圖像以便將來更快地顯示圖像。我有兩個主要問題:如何使用Javascript緩存圖像

  1. 如何緩存圖像?
  2. 如何在緩存圖片後使用圖片? (和公正的驗證,如果圖像是第A緩存,可以從緩存中調用它來使用它在頁面B,對吧?)

而且,是有可能設置該圖像的緩存版本將過期?

它將是否包含一個例子和/或到一個頁面的鏈接描述該進一步不勝感激。

我們很好利用兩種原料Javascript或jQuery的版本。

+10

你不知道。瀏覽器確實如此。 – Pointy 2012-04-20 04:07:59

+0

會自動執行瀏覽器緩存圖片嗎? – 2012-04-20 04:12:42

+6

@Logan:是的,瀏覽器會自動緩存圖片,只要您的服務器發送必要的標題以告訴瀏覽器緩存它是安全的。 (這些標題也可能會告訴瀏覽器到期時間,這是您問題的一部分。) – icktoofay 2012-04-20 04:18:31

回答

92

一旦圖像以任何方式被加載到瀏覽器中,它會在瀏覽器的緩存,它是用來在使用是否是在當前頁面或只要任何其他頁面將加載速度更快,下一次因爲圖像在從瀏覽器緩存到期之前使用。

因此,要預先緩存圖像,您只需將其加載到瀏覽器中即可。如果你想預處理一堆圖像,最好用javascript來完成,因爲它通常不會阻止從JavaScript完成頁面加載。你可以是這樣做的:

function preloadImages(array) { 
    if (!preloadImages.list) { 
     preloadImages.list = []; 
    } 
    var list = preloadImages.list; 
    for (var i = 0; i < array.length; i++) { 
     var img = new Image(); 
     img.onload = function() { 
      var index = list.indexOf(this); 
      if (index !== -1) { 
       // remove image from the array once it's loaded 
       // for memory consumption reasons 
       list.splice(index, 1); 
      } 
     } 
     list.push(img); 
     img.src = array[i]; 
    } 
} 

preloadImages(["url1.jpg", "url2.jpg", "url3.jpg"]); 

此功能可以根據需要被稱爲很多次,每一次,它只會增加更多的圖像到預緩存。

一旦圖像通過javascript被預加載像這樣,瀏覽器將它們放在它的緩存中,你可以在其他地方(在你的網頁中)引用正常的URL,瀏覽器將從它的緩存中獲取該URL而不是通過網絡。

最終隨着時間的推移,瀏覽器緩存可能會填滿並拋棄一段時間內未使用的最古老的東西。因此,最終,圖像將從緩存中清除,但它們應該停留一段時間(取決於緩存的大小以及其他瀏覽的次數)。每次圖像實際上再次預加載或在網頁中使用時,它會自動刷新其在瀏覽器緩存中的位置,以便它們不太可能從緩存中清除。

瀏覽器緩存是跨頁面的,因此它適用於加載到瀏覽器中的任何頁面。因此,您可以在網站的某個位置進行預緩存,然後瀏覽器緩存將適用於您網站上的所有其他頁面。


當如上預緩存,圖像被異步所以他們不會阻止你的頁面的加載或顯示加載。但是,如果您的頁面擁有大量自己的圖片,則這些預緩存圖片可以與頁面中顯示的圖片競爭帶寬或連接。通常情況下,這不是一個明顯的問題,但是在連接速度較慢的情況下,此預緩存可能會減慢主頁的加載速度。如果最後加載預加載圖像是可以的,那麼可以使用該函數的一個版本,該版本將等待開始預加載,直到所有其他頁面資源已經加載完畢。

function preloadImages(array, waitForOtherResources, timeout) { 
    var loaded = false, list = preloadImages.list, imgs = array.slice(0), t = timeout || 15*1000, timer; 
    if (!preloadImages.list) { 
     preloadImages.list = []; 
    } 
    if (!waitForOtherResources || document.readyState === 'complete') { 
     loadNow(); 
    } else { 
     window.addEventListener("load", function() { 
      clearTimeout(timer); 
      loadNow(); 
     }); 
     // in case window.addEventListener doesn't get called (sometimes some resource gets stuck) 
     // then preload the images anyway after some timeout time 
     timer = setTimeout(loadNow, t); 
    } 

    function loadNow() { 
     if (!loaded) { 
      loaded = true; 
      for (var i = 0; i < imgs.length; i++) { 
       var img = new Image(); 
       img.onload = img.onerror = img.onabort = function() { 
        var index = list.indexOf(this); 
        if (index !== -1) { 
         // remove image from the array once it's loaded 
         // for memory consumption reasons 
         list.splice(index, 1); 
        } 
       } 
       list.push(img); 
       img.src = imgs[i]; 
      } 
     } 
    } 
} 

preloadImages(["url1.jpg", "url2.jpg", "url3.jpg"], true); 
preloadImages(["url99.jpg", "url98.jpg"], true); 
+0

在這個例子中,你正在爲每個url創建一個新的Image對象。如果你在循環之外設置img變量並更新src,它應該具有相同的效果並減少資源 – cadlac 2014-07-11 16:03:45

+0

@cadlac - 但要確定瀏覽器實際上下載並緩存每個圖像,你必須等到一個圖像完成下載後再設置一個新的.src屬性。否則,瀏覽器可能會停止之前的下載並永遠不會成功緩存它。 – jfriend00 2014-07-11 20:10:27

+0

它似乎可以在不等待的情況下在較新版本的瀏覽器上運行,但是您可以說得很好。我將不得不在一些較舊的瀏覽器上試用它,看它是否兼容:) – cadlac 2014-07-14 17:47:13

10

爲@Pointy說你用JavaScript不緩存圖像,瀏覽器做到這一點。所以這可能是你要求的,可能不是......但你可以使用JavaScript預載圖像。通過將所有要預加載的圖像放入數組中,並將該數組中的所有圖像放入隱藏的img元素中,可以有效地預加載(或緩存)圖像。

var images = [ 
'/path/to/image1.png', 
'/path/to/image2.png' 
]; 

$(images).each(function() { 
var image = $('<img />').attr('src', this); 
}); 
+2

是否可以在一頁上預加載圖像(不顯示它),然後將其顯示在下一頁上? – 2012-04-20 04:18:58

+1

據我所知,如果您在一頁上預加載圖像,它將被輸入到瀏覽器緩存中,然後在任何其他頁面上顯示得更快。如果這是錯誤的,請有人糾正我。 – 2012-04-20 04:21:05

2

有幾件事情,你可以看看:

預加載您的圖像
在.htaccess文件設置一個緩存時間
圖像0​​文件大小和Base64編碼它們。

預壓: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/

緩存: http://www.askapache.com/htaccess/speed-up-sites-with-htaccess-caching.html

有用於base64編碼幾個不同的看法,有的說是HTTP請求拖垮帶寬,而其他人說的「感知」加載更好。我會把它留在空中。

1

我有一個similar answer異步通過JS預裝的圖像。動態加載它們與通常加載它們相同。他們會緩存。

用於高速緩存,你無法控制的瀏覽器,但你可以通過服務器設置。如果您需要按需加載真正新鮮的資源,則可以使用cache buster technique強制加載新資源。

1

即使你的問題說「使用JavaScript」,您可以使用link標籤的prefetch屬性預加載任何資產。在撰寫本文時(2016年8月10日),它不是在Safari瀏覽器的支持,但幾乎其他任何地方:在支持

<link rel="prefetch" href="(url)">

此處瞭解詳情: http://caniuse.com/#search=prefetch

注意,IE 9 ,因爲微軟已經停止對它們的支持,所以在caniuse矩陣中沒有列出10個。

所以如果你真的卡在使用javascript中,你可以使用jQuery這些元素動態添加到您的網頁,以及;-)

+0

不錯不錯不錯! – 2017-04-21 09:57:34

1

我使用了類似的技術來lazyload圖像,但不禁請注意,JavaScript在第一次加載時不會訪問瀏覽器緩存。

我的例子:

我已經在我的主頁旋轉旗幟4個圖像滑塊等待2秒,比的JavaScript加載下一個圖像,等待2秒,等等。

這些圖像具有獨特的URL,每當我修改它們時都會更改,因此它們將獲得將在瀏覽器中緩存一年的緩存標頭。

max-age: 31536000, public 

現在,當我打開瀏覽器Devtools並確保德「禁用緩存」選項處於非活動狀態並加載網頁的第一次(清除緩存後),所有圖像獲取獲取和擁有200個狀態。在橫幅中的所有圖像完整週期後,網絡請求停止並使用緩存的圖像。

現在,當我進行常規刷新或轉到子頁面並單擊後,緩存中的圖像似乎被忽略。我期望在Chrome devtools的「網絡」選項卡中看到「來自磁盤緩存」的灰色消息。相反,我看到請求每隔兩秒鐘傳遞一次綠色狀態圈,而不是灰色,我看到數據正在傳輸,所以我得到的印象是,根本沒有從JavaScript訪問緩存。它只是在每次頁面加載時獲取圖像。

因此,無論圖像的緩存策略如何,對主頁的每個請求都會觸發4個請求。

考慮到上述情況以及大多數網絡服務器和瀏覽器現在支持的新的http2標準,我認爲最好停止使用延遲加載,因爲http2會幾乎同時加載所有圖像。

如果這是Chrome Devtools中的一個錯誤,那真的讓人感到意外,我沒有人注意到這一點。 ;)

如果這是真的,使用lazyloading只會增加帶寬使用。

如果我錯了,請糾正我。 :)

0

我總是喜歡使用Konva JS: Image Events中提到的示例來加載圖像。

  1. 你必須圖像的URL作爲對象或陣列的列表,例如:

    var sources = { lion: '/assets/lion.png', monkey: '/assets/monkey.png' };

  2. 定義該函數定義,在那裏它接收圖像的URL列表和一個回調函數在它的參數列表,所以當它完成加載圖像,你可以在你的網頁上啓動excution:

function loadImages(sources, callback) { 
 
       var images = {}; 
 
       var loadedImages = 0; 
 
       var numImages = 0; 
 
       for (var src in sources) { 
 
        numImages++; 
 
       } 
 
       for (var src in sources) { 
 
        images[src] = new Image(); 
 
        images[src].onload = function() { 
 
         if (++loadedImages >= numImages) { 
 
          callback(images); 
 
         } 
 
        }; 
 
        images[src].src = sources[src]; 
 
       } 
 
      }

  • 最後,需要調用該函數。您可以從稱之爲例如jQuery的文檔準備
  • $(document).ready(function(){ loadImages(sources, buildStage); });