你如何在 Javascript 中缓存图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10240110/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 00:27:24  来源:igfitidea点击:

How do you cache an image in Javascript

javascriptjqueryimagecachingbrowser-cache

提问by Logan Besecker

My friends and I are working on a website where we would like to cache certain images in order to display them faster in the future. I have two main questions:

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

  1. How do you cache an image?
  2. How do you use an image once it has been cached? (and just to verify, if an image is cached on page A, it is possible to call it from the cache to use it on page B, right?)
  1. 你如何缓存图像?
  2. 图像被缓存后如何使用?(并且只是为了验证,如果图像缓存在页面 A 上,可以从缓存中调用它以在页面 B 上使用它,对吗?)

Also, is it possible to set whenthe cached version of the image will expire?

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

It would be much appreciated if an example and/or a link to a page which describes this further was included.

如果包含一个示例和/或指向进一步描述此内容的页面的链接,将不胜感激。

We're fine using either raw Javascript or the jQuery version.

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

回答by jfriend00

Once an image has been loaded in any way into the browser, it will be in the browser cache and will load much faster the next time it is used whether that use is in the current page or in any other page as long as the image is used before it expires from the browser cache.

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

So, to precache images, all you have to do is load them into the browser. If you want to precache a bunch of images, it's probably best to do it with javascript as it generally won't hold up the page load when done from javascript. You can do that like this:

因此,要预缓存图像,您要做的就是将它们加载到浏览器中。如果你想预缓存一堆图像,最好用 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"]);

This function can be called as many times as you want and each time, it will just add more images to the precache.

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

Once images have been preloaded like this via javascript, the browser will have them in its cache and you can just refer to the normal URLs in other places (in your web pages) and the browser will fetch that URL from its cache rather than over the network.

一旦通过 javascript 像这样预加载图像,浏览器会将它们保存在其缓存中,您只需在其他地方(在您的网页中)引用普通 URL,浏览器将从其缓存中获取该 URL,而不是通过网络。

Eventually over time, the browser cache may fill up and toss the oldest things that haven't been used in awhile. So eventually, the images will get flushed out of the cache, but they should stay there for awhile (depending upon how large the cache is and how much other browsing is done). Everytime the images are actually preloaded again or used in a web page, it refreshes their position in the browser cache automatically so they are less likely to get flushed out of the cache.

最终,随着时间的推移,浏览器缓存可能会填满并丢弃一段时间未使用的最旧的东西。所以最终,图像将从缓存中刷新,但它们应该在那里停留一段时间(取决于缓存有多大以及其他浏览完成了多少)。每次实际再次预加载图像或在网页中使用图像时,它都会自动刷新它们在浏览器缓存中的位置,因此它们不太可能从缓存中刷新。

The browser cache is cross-page so it works for any page loaded into the browser. So you can precache in one place in your site and the browser cache will then work for all the other pages on your site.

浏览器缓存是跨页面的,因此它适用于加载到浏览器中的任何页面。因此,您可以在站点中的一个位置进行预缓存,然后浏览器缓存将适用于您站点上的所有其他页面。



When precaching as above, the images are loaded asynchronously so they will not block the loading or display of your page. But, if your page has lots of images of its own, these precache images can compete for bandwidth or connections with the images that are displayed in your page. Normally, this isn't a noticeable issue, but on a slow connection, this precaching could slow down the loading of the main page. If it was OK for preload images to be loaded last, then you could use a version of the function that would wait to start the preloading until after all other page resources were already loaded.

如上所述进行预缓存时,图像是异步加载的,因此它们不会阻止页面的加载或显示。但是,如果您的页面有很多自己的图像,这些预缓存图像可能会与页面中显示的图像争夺带宽或连接。通常,这不是一个明显的问题,但在连接速度较慢的情况下,这种预缓存可能会减慢主页的加载速度。如果最后加载预加载图像是可以的,那么您可以使用该函数的一个版本,该版本会等待所有其他页面资源都已加载后才开始预加载。

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);

回答by Trav McKinney

as @Pointy said you don't cache images with javascript, the browser does that. so this may be what you are asking for and may not be... but you can preload images using javascript. By putting all of the images you want to preload into an array and putting all of the images in that array into hidden img elements, you effectively preload (or cache) the images.

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

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

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

回答by Tango Bravo

There are a few things you can look at:

您可以查看以下几点:

Pre-loading your images
Setting a cache time in an .htaccess file
File size of images and base64 encoding them.

预加载图像
在 .htaccess 文件中设置缓存时间
图像的文件大小和 base64 编码。

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

预加载:http: //perishablepress.com/3-ways-preload-images-css-javascript-ajax/

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

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

There are a couple different thoughts for base64 encoding, some say that the http requests bog down bandwidth, while others say that the "perceived" loading is better. I'll leave this up in the air.

对于 base64 编码有几种不同的想法,有人说 http 请求会降低带宽,而另一些人则说“感知”加载更好。我将把这个悬而未决。

回答by Brad Parks

Even though your question says "using javascript", you can use the prefetchattribute of a link tag to preload any asset. As of this writing (Aug 10, 2016) it isn't supported in Safari, but is pretty much everywhere else:

即使您的问题是“使用 javascript”,您也可以使用prefetch链接标签的属性来预加载任何资产。在撰写本文时(2016 年 8 月 10 日),Safari 不支持它,但几乎在其他任何地方都支持它:

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

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

More info on support here: http://caniuse.com/#search=prefetch

有关此处支持的更多信息:http: //caniuse.com/#search=prefetch

Note that IE 9,10 aren't listed in the caniusematrix because Microsoft has discontinued support for them.

请注意,IE 9,10 未列在caniuse矩阵中,因为 Microsoft 已停止对它们的支持。

So if you were really stuck on using javascript, you could use jquery to dynamically add these elements to your page as well ;-)

因此,如果您真的坚持使用 javascript,您也可以使用 jquery 将这些元素动态添加到您的页面中 ;-)

回答by Jean-Paul Ladage

I use a similar technique to lazyload images, but can't help but notice that Javascript doesn't access the browser cache on first loading.

我使用类似的技术来延迟加载图像,但不禁注意到 Javascript 在第一次加载时不会访问浏览器缓存。

My example:

我的例子:

I have a rotating banner on my homepage with 4 images the slider wait 2 seconds, than the javascript loads the next image, waits 2 seconds, etc.

我的主页上有一个旋转横幅,其中有 4 张图像,滑块等待 2 秒,然后 javascript 加载下一张图像,等待 2 秒等。

These images have unique urls that change whenever I modify them, so they get caching headers that will cache in the browser for a year.

这些图像具有独特的 url,每当我修改它们时都会发生变化,因此它们会获得缓存标头,这些标头将在浏览器中缓存一年。

max-age: 31536000, public

Now when I open Chrome Devtools and make sure de 'Disable cache' option is not active and load the page for the first time (after clearing the cache) all images get fetch and have a 200 status. After a full cycle of all images in the banner the network requests stop and the cached images are used.

现在,当我打开 Chrome Devtools 并确保 de 'Disable cache' 选项未激活并首次加载页面(清除缓存后)时,所有图像都被获取并具有 200 状态。在横幅中所有图像的完整循环之后,网络请求停止并使用缓存的图像。

Now when I do a regular refresh or go to a subpage and click back, the images that are in the cache seems to be ignored. I would expect to see a grey message "from disk cache" in the Network tab of Chrome devtools. In instead I see the requests pass by every two seconds with a Green status circle instead of gray, I see data being transferred, so it I get the impression the cache is not accessed at all from javascript. It simply fetches the image each time the page gets loaded.

现在,当我定期刷新或转到子页面并单击返回时,缓存中的图像似乎被忽略了。我希望在 Chrome devtools 的网络选项卡中看到一条灰色消息“来自磁盘缓存”。相反,我看到请求每两秒钟通过一个绿色状态圆圈而不是灰色,我看到数据正在传输,所以我得到的印象是根本没有从 javascript 访问缓存。它只是在每次加载页面时获取图像。

So each request to the homepage triggers 4 requests regardless of the caching policy of the image.

所以无论图片的缓存策略如何,对主页的每个请求都会触发 4 个请求。

Considering the above together and the new http2 standard most webservers and browsers now support, I think it's better to stop using lazyloading since http2 will load all images nearly simultaneously.

综合考虑以上内容以及大多数网络服务器和浏览器现在支持的新 http2 标准,我认为最好停止使用延迟加载,因为 http2 将几乎同时加载所有图像。

If this is a bug in Chrome Devtools it really surprises my nobody noticed this yet. ;)

如果这是 Chrome Devtools 中的一个错误,我真的很惊讶我还没有人注意到这一点。;)

If this is true, using lazyloading only increases bandwith usage.

如果这是真的,使用延迟加载只会增加带宽使用。

Please correct me if I'm wrong. :)

如果我错了,请纠正我。:)

回答by Per Quested Aronsson

Adding for completeness of the answers: preloading with HTML

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

<link rel="preload" href="bg-image-wide.png" as="image">

Other preloading features exist, but none are quite as fit for purpose as <link rel="preload">:

存在其他预加载功能,但没有一个像以下那样适合<link rel="preload">

  • <link rel="prefetch">has been supported in browsers for a long time, but it is intended for prefetching resources that will be used in the next navigation/page load (e.g. when you go to the next page). This is fine, but isn't useful for the current page! In addition, browsers will give prefetch resources a lower priority than preload ones — the current page is more important than the next. See Link prefetching FAQfor more details.
  • <link rel="prerender">renders a specified webpage in the background, speeding up its load if the user navigates to it. Because of the potential to waste users bandwidth, Chrome treats prerender as a NoState prefetch instead.
  • <link rel="subresource">was supported in Chrome a while ago, and was intended to tackle the same issue as preload, but it had a problem: there was no way to work out a priority for the items (as didn't exist back then), so they all got fetched with fairly low priority.
  • <link rel="prefetch">浏览器已支持很长时间,但它旨在预取将在下一次导航/页面加载中使用的资源(例如,当您转到下一页时)。这很好,但对当前页面没有用!此外,浏览器会给预取资源的优先级低于预加载资源——当前页面比下一个页面更重要。有关更多详细信息,请参阅链接预取常见问题解答
  • <link rel="prerender">在后台呈现指定的网页,如果用户导航到它,则加速其加载。由于可能浪费用户带宽,Chrome 将预渲染视为 NoState 预取。
  • <link rel="subresource">不久前在 Chrome 中受支持,旨在解决与预加载相同的问题,但它有一个问题:无法确定项目的优先级(因为当时不存在),所以他们都以相当低的优先级获取。

There are a number of script-based resource loaders out there, but they don't have any power over the browser's fetch prioritization queue, and are subject to much the same performance problems.

有许多基于脚本的资源加载器,但它们对浏览器的 fetch 优先级队列没有任何权力,并且受到几乎相同的性能问题的影响。

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

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

回答by Joseph

I have a similar answerfor asynchronous preloading images via JS. Loading them dynamically is the same as loading them normally. they will cache.

我对通过 JS 异步预加载图像有类似的答案。动态加载它们与正常加载它们是一样的。他们会缓存。

as for caching, you can't control the browser but you can set it via server. if you need to load a really fresh resource on demand, you can use the cache buster techniqueto force load a fresh resource.

至于缓存,您无法控制浏览器,但可以通过服务器进行设置。如果您需要按需加载真正新鲜的资源,您可以使用缓存破坏技术来强制加载新鲜资源。

回答by Mehdi Bouzidi

Nowdays, there is a new technique suggested by googleto cache and improve your image rendering process:

现在,谷歌推荐了一种新技术来缓存和改进您的图像渲染过程:

  1. Include the JavaScript Lazysizes file: lazysizes.js
  2. Add the file to the html file you want to use in: <script src="lazysizes.min.js" async></script>
  3. Add the lazyloadclass to your image: <img data-src="images/flower3.png" class="lazyload" alt="">
  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="">

回答by Mahdi Alkhatib

I always prefer to use the example mentioned in Konva JS: Image Eventsto load images.

我总是喜欢使用Konva JS: Image Events 中提到的示例来加载图像。

  1. You need to have a list of image URLs as object or array, for example:

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

  2. Define the Function definition, where it receives list of image URLs and a callback function in its arguments list, so when it finishes loading image you can start excution on your web page:

  1. 您需要将图像 URL 列表作为对象或数组,例如:

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

  2. 定义函数定义,它接收图像 URL 列表和参数列表中的回调函数,因此当它完成加载图像时,您可以在您的网页上开始执行:

    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];
                }
            }

  1. Lastly, you need to call the function. You can call it for example from jQuery's Document Ready
  1. 最后,您需要调用该函数。例如,您可以从jQueryDocument Ready调用它

$(document).ready(function (){ loadImages(sources, buildStage); });

$(document).ready(function (){ loadImages(sources, buildStage); });

回答by magzalez

Yes, the browser caches images for you, automatically.

是的,浏览器会自动为您缓存图像。

You can, however, set an image cache to expire. Check out this Stack Overflow questions and answer:

但是,您可以将图像缓存设置为过期。看看这个 Stack Overflow 问题和答案:

Cache Expiration On Static Images

静态图像上的缓存过期