如何在Javascript中缓存图像

Log*_*ker 70 javascript jquery caching image browser-cache

我的朋友和我正在一个网站上工作,我们希望缓存某些图像,以便将来更快地显示它们.我有两个主要问题:

  1. 你如何缓存图像?
  2. 缓存后如何使用图像?(并且只是为了验证,如果图像在页面A上缓存,则可以从缓存中调用它以在页面B上使用它,对吧?)

此外,有可能设置时,图像的缓存版本将到期?

如果包括进一步描述这一点的页面的示例和/或链接,将会非常感激.

我们可以使用原始Javascript或jQuery版本.

jfr*_*d00 116

一旦图像以任何方式加载到浏览器中,它将在浏览器缓存中,并且在下次使用时加载速度会快得多,无论该用途是在当前页面还是在任何其他页面中,只要图像是在从浏览器缓存过期之前使用.

因此,要预先缓存图像,您只需将它们加载到浏览器中即可.如果你想预先处理一堆图像,最好用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"]);
Run Code Online (Sandbox Code Playgroud)

可以根据需要多次调用此函数,每次都可以向预缓存添加更多图像.

一旦通过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);
Run Code Online (Sandbox Code Playgroud)

  • @cadlac - 但要确定浏览器实际上会下载和缓存每个图像,您必须等到一个图像完成下载后再设置新的 .src 属性。否则浏览器可能会停止先前的下载并且永远不会成功缓存它。 (3认同)

Per*_*son 13

添加答案的完整性:使用 HTML 预加载

\n\n
<link rel="preload" href="bg-image-wide.png" as="image">\n
Run Code Online (Sandbox Code Playgroud)\n\n

还存在其他预加载功能,但没有一个比以下功能更适合目的<link rel="preload">

\n\n
    \n
  • <link rel="prefetch">长期以来一直受到浏览器的支持,\n但它旨在预取将在\n下一个导航/页面加载中使用的资源(例如,当您转到下一页时)。这很好,但对当前页面没有用!此外,浏览器\n将为预取资源提供比预加载资源更低的优先级\xe2\x80\x94\n当前页面比下一个页面更重要。请参阅链接预取\n常见问题解答以了解更多详细信息。
  • \n
  • <link rel="prerender">在后台呈现指定的网页,如果用户导航到该网页,则可以加快其加载速度。由于可能会浪费用户带宽,Chrome\n将预渲染视为 NoState 预取。
  • \n
  • <link rel="subresource"> 不久前在 Chrome 中得到了支持,并且\n旨在解决与预加载相同的问题,但它有一个问题:\n无法确定项目的优先级(因为当时不\n存在) ,所以它们都是以相当低的优先级获取的。
  • \n
\n\n

有许多基于脚本的资源加载器,但它们对浏览器的获取优先级队列没有任何能力,并且会遇到许多相同的性能问题。

\n\n

来源:https ://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content

\n


Tra*_*ney 11

正如@Pointy所说你不用javascript缓存图像,浏览器会这样做.所以这可能是你要求的,可能不是......但你可以使用javascript预加载图像.通过将您想要预加载的所有图像放入数组并将该数组中的所有图像放入隐藏的img元素中,您可以有效地预加载(或缓存)图像.

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

$(images).each(function() {
var image = $('<img />').attr('src', this);
});
Run Code Online (Sandbox Code Playgroud)

  • 是否可以在一个页面上预加载图像(不显示它),然后在下一页显示它? (2认同)
  • 据我所知,如果您在一个页面上预加载图像,它将被输入到浏览器缓存中,然后在任何其他页面上显示得更快。如果这是错误的,请有人纠正我。 (2认同)

Meh*_*idi 7

如今,谷歌建议了一种新技术来缓存和改进图像渲染过程:

  1. 包含 JavaScript Lazysizes 文件:lazysizes.js
  2. 将文件添加到您要使用的 html 文件中: <script src="lazysizes.min.js" async></script>
  3. lazyload类添加到您的图像中: <img data-src="images/flower3.png" class="lazyload" alt="">