Как сделать кэширование картинок
Управление загрузкой изображений
Быстрая и плавная загрузка изображений — это одна из немаловажных составляющих хорошего веб-интерфейса. Кроме того, появляется все больше сайтов, использующие крупные фотографии в дизайне, таким проектам особенно важно следить за корректной загрузкой графики. В этой статье описано несколько техник, которые помогут контролировать загрузку изображений.
Использование контейнера для каждого изображения
Простой способ, который можно применить к любому изображению на сайте. Заключается в том, что каждая картинка оборачивается в DIV, который предотвращает построчную загрузку:
С помощью контейнера можно контролировать соотношение сторон картинки, а также использовать индикатор загрузки, что очень удобно, если изображения тяжелые.
Например, чтобы задать соотношение сторон 4:3, можно использовать следующий CSS:
Для того, чтобы изображение отображалось в браузере только после полной подгрузки, необходимо добавить событие onload для изображения и использовать JavaScript, который будет обрабатывать событие:
Код функции внутри тега HEAD должен быть расположен в самом конце, после любого jQuery или другого плагина. После полной подгрузки изображения его необходимо показать на странице:
Для эффекта плавного появления картинки можно использовать CSS3 transition:
Живой пример этого способа можно посмотреть на Codepen.
Использование контейнера для множества изображений
Предыдущий способ хорошо подходит для отдельных изображений, а что если на странице их много, например галерея фотографий или слайдер? Подгружать сразу все нецелесообразно — картинки могут много весить. Для решения этой проблемы можно заставить JavaScript’ом загружать только нужные в данный момент времени изображения. Пример HTML-разметки для слайдшоу:
Используем функцию slideLoaded(), чтобы контролировать процесс:
Подгруженным изображениям присваивается класс loaded, а также отображается общий прогресс. И снова, JavaScript должен быть помещен в конец тега HEAD, после всего остального.
Кэширование
На графически тяжелых сайтах можно в фоновом режиме, незаметно для пользователя, загружать изображения в кэш браузера. Например, есть многостраничный сайт, на одной из внутренних страниц которого есть много графического контента. В этом случае будет целесообразно подгружать изображения в кэш еще до того, как пользователь перешел на нужную страницу. адреса картинок в массиве:
Когда посетитель заходит на сайт, после загрузки главной страницы, начинают загружаться изображения в кэш. Для того, чтобы кэширование не мешало отображению текущего контента, необходимо функционал JavaScript добавить в событие window load:
Такой способ улучшает удобство использования сайта, однако дает дополнительную нагрузку на сервер. Это нужно иметь в виду при внедрении подобного функционала. Кроме того, необходимо обязательно учитывать возможные пути посетителей на сайте и кэшировать изображения, расположенные на страницах, которые пользователь вероятнее всего посетит. Чтобы понять такие пути по сайту, необходимо анализировать статистику посещаемости.
Загрузка по событию
способ заключается в том, что изображения начинают подгружаться после определенного события. Это увеличивает производительность и экономит трафик пользователя. HTML-разметка:
Стоит заметить, что URL изображение задано в data-src, а не в src. Это необходимо, чтобы браузер не загружал картинку сразу. Вместо этого в src загружается прозрачный пиксель в GIF, заданный в base64, что уменьшает количество обращений к серверу.
Остается только при нужном событии изменить значение src на data-src. JavaScript позволяет загружать изображения постепенно:
Шпаргалка: кеширование картинок, CSS и JS в NGINX
Заметка для тех, кто не специалист в NGINX, а проблему нужно решить быстро.
Допустим, у вас на сервере стоит NGINX и вы хотите, чтобы вся статика кешировалась у клиента. В конфиге хоста NGINX пропишите это:
server <
listen 80;
server_name mysite.com;
.
# Задаем правила обработки статического контента (типов файлов можно поставить и больше)
location
* ^.+\.(jpg|jpeg|gif|png|ico|css|pdf|ppt|txt|bmp|rtf|js)$ <
root /path/to/document/root/; # Путь к корню вашего сайта
access_log off; # не пишем логи
expires 3d; # кешируем у клиента на 3 дня
>
>
Проверить можно в FireBug во вкладке NET: обновите страницу 2 раза и посмотрите код ответа. Если 200 ОК, то не работает. Если 304 Not Modified, то работает.
Неплохо ускоряет работу сайта.
AdBlock похитил этот баннер, но баннеры не зубы — отрастут
Комментарии 30
Вставлю свои пять копеек: если вы используете Drupal с модулем ImageCache (а если вы используете первое, то второе вам по-любому пригодится, если на вашем сайте встречаются хоть какие-то картинки, которые надо как-то обрабатывать, например, укладывая в галереи или выводя в виде миниатюр), то перед указанным обработчиком, надо вставить ещё один, иначе картинки генериться не будут.
Не совсем. Если быть точнее, то про ту часть, которая в шпаргалке подчеркнута. Исходим из того, что то, что не подчеркнуто, уже было в конфиге.
Ну, про 100 дней вы, конечно, правы. В действительности достаточно и 7 дней. Может быть и меньше (зависит от того, как как часто меняется статический контент).
Про мегабайтные картинки. Бывают еще картинки по 200К. Например фоновые. И не очень быстрый интернет-канал на работе у людей. Тут кеширование тоже помогает.
И я не говорю о том, что вынос статики в nginx НЕ ускоряет работу клиента с сайтом. Я говорю о том, что кеширование картинок дополнительно ускоряет работу.
Шпаргалка, она на то и шпаргалка, что короткая и не копирует документацию системы, а просто показывает визуально — что сделать и где. Или не так?
Скажите, о чем мы сейчас спорим? О том, что «шпаргалка» написана неправильно?
Как-то раз приходилось делать так, как у вас описано в последнем варианте, но мы просто добавляли к имени вес файла. Что-то типа:
почему бы просто не инкрементировать версию CSS/JS файла через доп параметр типа
Очень просто: styles.css?v=1.1
Где v — версия файла или даже пакета файлов.
> Кстати а вы не знаете, будет ли такой запрос всегда нормально кешироваться?
> Я же говорил о том, что хочется изящного и безгеморойного решения.
Как-то так это в nginx пишется:
А номерок не забывать обновлять… Как пару раз наткнётесь на разлетевшийся макет, так и научитесь не забывать 🙂
А нужно делать так, что бы браузер вообще не посылал запрос, на который получит «304 Not Modified»:
Кроме того регулярное выражение в location — это медленно, лучше просто иметь директорию или даже домен для статики. и тогда:
А выключать логи для статики — правильно, я забыл про это.
Тут бы еще надо упомянуть плагин YSlow для FireBug, который покажет все незакэшированные файлы, несжатый js и много другой полезной информации, а также выставит странице общую оценку.
Про логи здорово, спасибо за наводку, как-то не думал об этом
> expires 3d; # кешируем у клиента на 3 дня
> Проверить можно в FireBug во вкладке NET:
> обновите страницу 2 раза и посмотрите код ответа.
> Если 200 ОК, то не работает. Если 304 Not Modified, то работает.
Не точная методика проверки. При правильном кешировании вообще не должно быть запросов к серверу. Нужно не обновлять страницу в браузере, а щелкать по ссылкам — ходить то на одну страницу, то на другую и обратно.
304 Not Modified получается когда принудительно обновляем страницу или когда протухает время кеширования контента. Тогда браузер отправляет HTTP запрос серверу с заголовком If-Modified-Since (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html). Сервер на этот запрос высылает контент, если файл был модифицирован, иначе говорит «304 Not Modified»…
Expires не имеет смысла выставлять на время, бОльшее 1 часа потому что:
1) Основная масса пользователей проводит на сайте время, меньшее 1 часа.
2) При протухании контента браузер отправит на сервер запрос с If-Modified-Since и сервер не будет заново закачивать контен в браузер, а просто отдаст короткий ответ 304 Not Modified
Осмелюсь порекомендовать устанавливать
*
^.+\.(html|htm|css|xml|rss|gif|jpeg|jpg|js|atom|mml|txt|jad|wml|htc|png|tif|tiff|wbmp|ico|jng|bmp|jar|war|ear|hqx|doc|pdf|ps|eps|ai|rtf|xls|ppt|wmlc|xhtml|cco|jardiff|jnlp|run|pl|pm|prc|pdb|rar|rpm|sea|swf|sit|tcl|tk|der|pem|crt|xpi|zip|bin|exe|dll|deb|dmg|eot|iso|img|msi|msp|msm|mid|midi|kar|mp3|ra|3gpp|3gp|mpeg|mpg|mov|flv|mng|asx|asf|wmv|avi|rar)$
<
root /var/www/DevVmPhp;
#Try to handle unavailable files with Apache
error_page 400 401 402 403 404 405 406 = @fallback;
>
Т.е. если файлика в статичном контенте нету, то запросить и отдать от сервера, а не просто возвращать 404
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.
Кэширование сайта и кэш браузера
Эффективная схема кэширования сайта в браузере обеспечивает высокую скорость загрузки веб-страниц при повторных обращениях к ним.
Содержание
Что такое кэш браузера и кэширование сайта?
Кэш браузера (Browser Cache) — временные файлы ресурсов веб-страниц сайта, сохраняемые браузером для последующего отображения в нём при повторном обращении к соответствующим страницам.
Процесс определения и сохранения кэша в браузере называется браузерным кэшированием (Browser Caching).
Браузерное кэширование можно представить следующим образом:
При повторных запросах этой веб-страницы браузер будет использовать файлы из кэша сайта. Срок кэширования определяется браузером согласно ответу сервера относительно каждого отдельного типа файла.
Как кэш браузера влияет на скорость загрузки сайта?
Правильная настройка кэширования веб-страниц позволяет значительно увеличить скорость загрузки сайта за счёт:
Кроме этого, браузерное кэширование значительно экономит веб-трафик клиента, исключая повторное скачивание файлов (картинок, скриптов, стилей) — они будут браться из кэша сайта.
Благодаря кешированию пользователи, повторно посещающие ваш сайт, тратят меньше времени на загрузку страниц.
Google Developers
Как проверить кэширование сайта в браузере?
Существует ряд способов проверки браузерного кэширования ресурсов сайта:
Проверка в браузере Chrome
Первый способ: обратиться к инструментам веб-разработчика, предоставляемым самим браузером. Рассмотрим на примере браузера Chrome:
Если файл кэшируется, то в колонке Size вместо размера файла будет отображаться запись (from memory cache) или (from disk cache):
Обратите внимание, насколько уменьшился объём передаваемых данных из примера на картинках: 3.8 МБ при первичном обращении и 601 КБ при повторном. При этом скорость загрузки страницы сайта снизилась с 12.45 до 7.77 секунд.
Активируйте чекбокс Disable cache во вкладке Network в панели инструментов Chrome, чтобы просмотреть исходный размер и скорость загрузки ресурсов веб-страницы при первичном обращении к ней.
Сервис PageSpeed Insights
Сервис от Google при обнаружении проблем с кэшированием ресурсов проверяемой веб-страницы выдаёт рекомендацию «Используйте кеш браузера». При клике по ссылке «Как исправить?» развернется список файлов, для которых необходимо оптимизировать настройки кэширования в браузере:
Сервис Pingdom Website Speed Test
Pingdom Website Speed Test — качественный популярный сервис проверки скорости загрузки сайта. Подобно сервису PageSpeed Insights, он указывает на проблемы со скоростью загрузки и даёт свои рекомендации. Каждому фактору сервис присваивает определённый рейтинг (Grade).
Фактор кэширования файлов в браузере называется «Leverage browser caching»:
Какие файлы сайта должны кэшироваться?
Ресурсы веб-страниц делятся на 2 группы:
Динамические Эти ресурсы не хранятся на сервере, а генерируются его средствами при запросах веб-страниц. К таким ресурсам обычно относят HTML-код, который может генерироваться посредством PHP на серверах Apache. Статические Такие ресурсы хранятся на сервере. Как правило, к ним относится медиа-контент (картинки и видео), а также файлы стилей, скриптов и шрифтов
Для большинства сайтов подходит схема кэширования всех статических ресурсов.
Заголовки кеширования должны применяться ко всем кешируемым статическим ресурсам, а не только к некоторым из них (например, изображениям). Кешируемые ресурсы включают файлы JavaScript и CSS, графические и другие файлы (мультимедийное содержание, файлы PDF и т. д.). Обычно код HTML не является статическим ресурсом и по умолчанию не считается кешируемым.
Google Developers
Сроки кэширования файлов в браузере
Возможной проблемой может быть обновление на сайте статических ресурсов, для которых установлен большой срок хранения в кэше.
Например, разработчик может обновить CSS-свойства в файлах стилей и HTML-код, но в кэше браузера пользователей могут храниться старые CSS-файлы. В результате пользователи при обращении к веб-странице могут видеть искаженный дизайн, т. к. HTML-код будет обновлен, но потерявший актуальность файл стилей будет загружаться из кэша сайта, ведь для него установлен большой срок хранения.
Чтобы избежать подобных проблем, необходимо настроить браузерное кэширование, правильно определив сроки хранения типов файлов.
Продолжительность хранения статических ресурсов в кеше должна составлять не менее недели. Внешние ресурсы (объявления, виджеты и др.) должны храниться не менее 1 дня.
Google Developers
Сроки кэширования файлов определяют значения специальных HTTP-заголовков:
Заголовок Expires
До момента наступления этой даты файл будет браться из кэша сайта в браузере. Такая схема исключает лишние запросы к серверу, сравнивающие кэшированный файл с файлом на сервере, но неудобство может быть вызвано привязкой к определённой дате, ведь файл может быть обновлён на сервере до её наступления.
Заголовок Cache-Control
Браузерное кэширование по схеме HTTP-заголовка Cache-Control является наиболее гибким и актуальным.
Пока не пройдёт указанное время с момента получения файла, он будет браться из кэша браузера.
Директивы заголовка Cache-Control
Заголовок Cache-Control может содержать одну или несколько директив, перечисленных через запятую. Это позволяет управлять кэшированием файлов более гибко.
Директива max-age
Как указывалось выше, с помощью этой директивы сервер даёт знать браузеру, на какой срок можно кэшировать файл. В качестве значения применяется цифра, обозначающая количество секунд.
Единица времени | Количество секунд |
---|---|
Секунда | 1 |
Минута | 60 |
Час | 3600 |
Сутки | 86400 |
Неделя | 604800 |
Месяц | 2592000 |
Год | 31536000 |
Директива no-cache
Вопреки названию, браузер будет кэшировать файл, переданный сервером с данным заголовком. Однако прежде, чем в дальнейшем брать его из кэша, браузер должен делать запрос к серверу на проверку его изменений. Если файл на сервере не изменился, браузер заберёт его из кэша, в ином случае сервер передаст обновлённую версию файла.
Директива no-store
Эта директива запрещает сохранять файл браузеру и в других промежуточных кэшах (CDN, прокси-сервера).
Директива public
Эта директива разрешает кэшировать файл как в браузере пользователя, так и в промежуточных кэшах (CDN, прокси-сервера). Применяется по умолчанию.
Директива private
Директива private разрешает кэшировать файл только в браузере пользователя, но не в промежуточных кэшах (CDN, прокси-сервера). Обычно применяется для кэширования персональных данных, актуальных для конечного пользователя.
Сравнение версий файлов в кэше и на сервере
Схему кэширования могут определять HTTP-заголовки для сравнение версий файлов в кэше и на сервере:
Заголовки Last-Modified и If-Modified-Since
Данную схему кэширования можно представить следующим образом:
Браузер делает первичный запрос веб-страницы.
Полученные файлы кэшируются браузером.
Если значения If-Modified-Since и Last-Modified совпадают, сервер отправляет браузеру ответ в виде значения 304 (Not Modified) : файл не претерпел изменений, и его можно брать из кэша. В ином случае сервер вновь передаёт файл в браузер.
К минусам данной схемы кэширования можно отнести постоянные проверяющие актуальность файлов HTTP-запросы If-Modified-Since к серверу.
Заголовки ETag и If-None-Match
Недостатком данной схемы также являются постоянные проверяющие запросы If-None-Match к серверу.
Правильная схема кэширования файлов в браузере
В идеале браузерное кэширование должно функционировать следующим образом:
При отсутствии HTTP-заголовков, определяющих схему кэширования файлов, она будет осуществляться браузером по умолчанию.
Поэтому ответ сервера для кэшируемого файла должен содержать два заголовка, определяющих эффективную схему кэширования:
Для всех кешируемых ресурсов нужно обязательно указывать один заголовок из пары Expires и Cache-Control max-age, а также один заголовок из пары Last-Modified и ETag.
Google Developers
Такой подход исключает лишние запросы к серверу за счет установленного срока кэширования (определённого с помощью заголовка Expires или Cache-control: max-age ), а также исключает повторное скачивание ресурса по окончании срока кэширования за счет его проверки на наличие изменений (с помощью заголовков Last-Modified или ETag ).
Включение и настройка кэширования сайта в браузере
Настройка браузерного кэширования осуществляется посредством редактирования конфигурационных файлов сервера (httpd.conf, .htaccess, nginx.conf).
Модуль mod_expires для сервера Apache
Не вдаваясь в подробности синтаксиса настройки данного модуля, приведем пример готовой конфигурации по включению браузерного кэширования на сайте с комментариями в коде:
Подробности о синтаксисе и настройках модуля mod_expires можно узнать в официальной документации.
Модуль mod_headers для сервера Apache
Для формирования HTTP-заголовков Cache-Control на серверах Apache применяется модуль mod_headers.
Настройка модуля подразумевает использование регулярных выражений для определения типов файлов, для которых будут формироваться заголовки Cache-Control :
Если настройки не вступят в силу, неободимо обратиться в техническую поддержку хостинга: возможно, модуль mod_headers не активирован на сервере.
Подробности о синтаксисе и настройках модуля mod_headers можно узнать в официальной документации.
Модуль ngx_http_headers_module для сервера Nginx
Для определения схемы кэширования на сервере Nginx применяется модуль ngx_http_headers_module, позволяющий настраивать любые заголовки ответов сервера.
Настройка заголовков Expires на Nginx
Настройка заголовков Cache-Control на Nginx
Указанный выше код можно скопировать в файл nginx.conf для применения данных настроек к сайту.
Если настройки не вступят в силу, необходимо обратиться в техническую поддержку хостинга: возможно, модуль ngx_http_headers_module не активирован на сервере.
Подробности о синтаксисе и настройках модуля ngx_http_headers_module можно узнать в официальной документации.
Проверка HTTP-заголовков ответа сервера
Рассмотрим процесс проверки передаваемых сервером заголовков на примере Chrome: