Как кешировать изображение в Javascript

Мои друзья и я работаем над веб-сайтом, где мы хотели бы кэшировать определенные изображения, чтобы отображать их быстрее в будущем. У меня есть два основных вопроса:

  • Как кешировать изображение?
  • Как вы используете изображение после кэширования? (и просто для проверки, если изображение кэшируется на странице A, можно вызвать его из кеша, чтобы использовать его на странице B, правильно?)

Кроме того, возможно ли установить, когда срок действия кешированной версии изображения истечет?

Было бы очень полезно, если бы был приведен пример и/или ссылка на страницу, которая описывает это далее.

Мы отлично используем либо сырой Javascript, либо версию jQuery.

Ответ 1

Как только изображение каким-либо образом загрузилось в браузер, оно будет находиться в кеше браузера и будет загружаться намного быстрее при следующем использовании, будь то на текущей странице или на любой другой странице, пока изображение используется до истечения срока его действия из кеша браузера.

Таким образом, для предварительного просмотра изображений все, что вам нужно сделать, это загрузить их в браузер. Если вы хотите прецедентировать кучу изображений, вероятно, лучше всего сделать это с помощью 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 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 из своего кеша, чем по сети.

Со временем кеш браузера может заполнить и бросить самые старые вещи, которые не использовались в течение некоторого времени. Таким образом, изображения будут выгружены из кеша, но они должны оставаться там на некоторое время (в зависимости от того, насколько велик кеш и сколько других браузеров сделано). Каждый раз, когда изображения на самом деле предварительно загружаются или используются на веб-странице, он автоматически обновляет свою позицию в кеше браузера, поэтому они с меньшей вероятностью выходят из кеша.

Кэш браузера является кросс-страницей, поэтому он работает для любой страницы, загруженной в браузер. Таким образом, вы можете выполнить предварительную проверку в одном месте на своем сайте, а кеш браузера будет работать для всех других страниц вашего сайта.


При предварительной подготовке, как показано выше, изображения загружаются асинхронно, поэтому они не будут блокировать загрузку или отображение вашей страницы. Но, если ваша страница имеет множество собственных изображений, эти изображения precache могут конкурировать за полосу пропускания или соединения с изображениями, отображаемыми на вашей странице. Обычно это не является заметной проблемой, но при медленном соединении эта предварительная подготовка может замедлить загрузку главной страницы. Если бы было нормально загружать изображения предварительной загрузки, то вы могли бы использовать версию функции, которая будет ждать, чтобы начать предварительную загрузку до тех пор, пока не будут загружены все остальные ресурсы страницы.

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

Ответ 2

поскольку @Pointy сказал, что вы не кэшируете изображения с помощью javascript, браузер делает это. так что это может быть то, о чем вы просите, а может и не быть... но вы можете предварительно загрузить изображения с помощью javascript. Поместив все изображения, которые вы хотите предварительно загрузить в массив, и поместив все изображения в этот массив в скрытые элементы img, вы эффективно загружаете (или кешируете) изображения.

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

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

Ответ 3

Есть несколько вещей, на которые вы можете обратить внимание:

Предварительная загрузка изображений
Установка времени кеша в файле .htaccess
Размер файлов изображений и 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-запросы увязывают пропускную способность, в то время как другие говорят, что "воспринимаемая" загрузка лучше. Я оставлю это в воздухе.

Ответ 4

У меня есть аналогичный ответ для асинхронной предварительной загрузки изображений через JS. Загрузка их динамически такая же, как и загрузка их в обычном режиме. они будут кэшировать.

как и для кеширования, вы не можете управлять браузером, но вы можете установить его через сервер. если вам нужно загрузить действительно свежий ресурс по запросу, вы можете использовать метод кэширования кэша, чтобы принудительно загрузить новый ресурс.

Ответ 5

Даже если ваш вопрос говорит "используя javascript", вы можете использовать атрибут prefetch тега ссылки для предварительной загрузки любого актива. На момент написания этой статьи (10 августа 2016 г.) он не поддерживается в Safari, но почти везде:

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

Подробнее о поддержке здесь: http://caniuse.com/#search=prefetch

Обратите внимание, что IE 9,10 не указаны в матрице caniuse, потому что Microsoft прекратила поддержку для них.

Итак, если вы действительно застряли в использовании javascript, вы можете использовать jquery для динамического добавления этих элементов на свою страницу; -)

Ответ 6

Я использую подобный метод для lazyload изображений, но не могу не заметить, что Javascript не имеет доступа к кешу браузера при первой загрузке.

Мой пример:

У меня есть вращающийся баннер на моей домашней странице с 4-мя изображениями, которые ждут ползунки на 2 секунды, чем javascript загружает следующее изображение, ждет 2 секунды и т.д.

У этих изображений есть уникальные URL-адреса, которые меняются, когда я их изменяю, поэтому они получают кеширующие заголовки, которые будут кэшироваться в браузере в течение года.

max-age: 31536000, public

Теперь, когда я открываю Chrome Devtools и убедитесь, что параметр "Отключить кеш" не активен и загружает страницу в первый раз (после очистки кеша), все изображения получают выборку и имеют статус 200. После полного цикла всех изображений в баннере сетевые запросы останавливаются и используются кешированные изображения.

Теперь, когда я делаю регулярное обновление или перехожу на подстраницу и нажимаю назад, изображения, которые находятся в кеше, кажется, игнорируются. Я ожидаю увидеть серое сообщение "из дискового кэша" на вкладке "Сеть" в Chrome devtools. Вместо этого я вижу, что запросы проходят каждые две секунды с кругом статуса зеленого цвета, а не серым, я вижу, что данные передаются, поэтому я получаю впечатление, что кэш не доступен вообще из javascript. Он просто извлекает изображение каждый раз, когда страница загружается.

Таким образом, каждый запрос на главную страницу запускает 4 запроса независимо от политики кэширования изображения.

Учитывая вышеизложенное и новый стандарт http2, который поддерживает большинство веб-серверов и браузеров, я думаю, что лучше прекратить использование lazyloading, поскольку http2 будет загружать все изображения почти одновременно.

Если это ошибка в Chrome Devtools, это действительно удивляет, что никто этого еще не заметил.;)

Если это верно, использование lazyloading только увеличивает использование полосы пропускания.

Пожалуйста, поправьте меня, если я ошибаюсь.:)

Ответ 7

Да, браузер автоматически кэширует изображения для вас.

Однако вы можете установить срок действия кэша изображений. Проверьте этот вопрос и ответьте на вопрос о переполнении стека:

Срок действия кеша на статических изображениях

Ответ 8

Я всегда предпочитаю использовать пример, упомянутый в Konva JS: События изображения для загрузки изображений.

  • У вас должен быть список URL-адресов изображений как объект или массив, например:

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

  • Определите определение функции, в которой он получает список 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];
                }
            }