2012-04-20 60 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); });