Как реализовать кэширование в браузере с помощью модуля заголовка Nginx в Ubuntu 16.04

Вступление

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

Это можно сделать разными способами, но одним из наиболее важных шагов является настройкаbrowser caching. Это говорит браузеру, что файлы, загруженные один раз, могут быть повторно использованы из локальных копий вместо того, чтобы снова и снова запрашивать у них сервер. Чтобы сделать это, должны быть введены новые заголовки ответа HTTP, сообщающие браузеру, как себя вести.

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

Предпосылки

Чтобы следовать этому уроку, вам понадобится:

В дополнение к модулю заголовка мы также будем использовать модуль карты Nginx в этой статье. Чтобы узнать больше о модуле карты, вы можете прочитатьHow To Use Nginx’s map Module on Ubuntu 16.04.

[[step-1 -—- created-test-files]] == Шаг 1. Создание тестовых файлов

На этом шаге мы создадим несколько тестовых файлов в каталоге Nginx по умолчанию. Мы будем использовать эти файлы позже, чтобы проверить поведение Nginx по умолчанию, а затем проверить, работает ли кэширование в браузере.

Чтобы принять решение о том, какой тип файла подается по сети, Nginx не анализирует содержимое файла; это было бы слишком медленно. Вместо этого он просто ищет расширение файла, чтобы определитьMIME type файла, которое обозначает цель файла.

Из-за этого поведения содержимое наших тестовых файлов не имеет значения. Правильно присвоив имена файлам, мы можем обмануть Nginx, думая, что, например, один совершенно пустой файл - это изображение, а другой - таблица стилей.

Создайте файл с именемtest.html в каталоге Nginx по умолчанию, используяtruncate. Это расширение означает, что это HTML-страница.

sudo truncate -s 1k /var/www/html/test.html

Таким же образом создадим еще несколько тестовых файлов: один файл изображенияjpg, одну таблицу стилейcss и один файл JavaScriptjs.

sudo truncate -s 1k /var/www/html/test.jpg
sudo truncate -s 1k /var/www/html/test.css
sudo truncate -s 1k /var/www/html/test.js

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

[[step-2 -—- verify-the-default-behavior]] == Шаг 2 - Проверка поведения по умолчанию

По умолчанию все файлы будут иметь одинаковое поведение по умолчанию. Чтобы исследовать это, мы будем использовать файл HTML, который мы создали на шаге 1, но вы можете запустить эти тесты с любым из файлов примеров.

Итак, давайте проверим, обслуживается лиtest.html какой-либо информацией о том, как долго браузер должен кэшировать ответ. Следующая команда запрашивает файл с нашего локального сервера Nginx и показывает заголовки ответа.

curl -I http://localhost/test.html

Вы должны увидеть несколько заголовков ответа HTTP:

Output: Nginx response headersHTTP/1.1 200 OK
Server: nginx/1.10.0 (Ubuntu)
Date: Sat, 10 Sep 2016 13:12:26 GMT
Content-Type: text/html
Content-Length: 1024
Last-Modified: Sat, 10 Sep 2016 13:11:33 GMT
Connection: keep-alive
ETag: "57d40685-400"
Accept-Ranges: bytes

Во второй предпоследней строке вы можете увидеть заголовокETag, который содержит уникальный идентификатор для этой конкретной ревизии запрошенного файла. Если вы повторно выполните предыдущую командуcurl, вы увидите точно такое же значениеETag.

При использовании веб-браузера значениеETag сохраняется и отправляется обратно на сервер с заголовком запросаIf-None-Match, когда браузер хочет снова запросить тот же файл - например, при обновлении страницы.

Мы можем смоделировать это в командной строке с помощью следующей команды. Убедитесь, что вы изменили значениеETag в этой команде, чтобы оно соответствовало значениюETag в предыдущем выводе.

curl -I -H 'If-None-Match: "57d40685-400"' http://localhost/test.html

Ответ теперь будет другим:

Output: Nginx response headersHTTP/1.1 304 Not Modified
Server: nginx/1.10.0 (Ubuntu)
Date: Sat, 10 Sep 2016 13:20:31 GMT
Last-Modified: Sat, 10 Sep 2016 13:11:33 GMT
Connection: keep-alive
ETag: "57d40685-400"

На этот раз Nginx ответит304 Not Modified. Он больше не будет отправлять файл по сети; вместо этого он сообщит браузеру, что может повторно использовать уже загруженный файл локально.

Это полезно, поскольку снижает сетевой трафик, но недостаточно хорош для достижения хорошей производительности кэширования. Проблема сETag заключается в том, что браузерalways отправляет запрос на сервер, спрашивая, может ли он повторно использовать свой кэшированный файл. Несмотря на то, что сервер отвечает 304 вместо того, чтобы отправлять файл снова, все еще требуется время, чтобы сделать запрос и получить ответ.

На следующем шаге мы будем использовать модуль заголовков для добавления информации управления кэшированием. Это заставит браузер локально кэшировать некоторые файлы без явного запроса сервера, если это нормально.

[[step-3 -—- configuring-cache-control-and-expires-headers]] == Шаг 3 - Настройка заголовков Cache-Control и Expires

В дополнение к заголовку проверки файлаETag, есть два заголовка ответа управления кешированием:Cache-Control иExpires. Cache-Control - это более новая версия, у которой больше опций, чем уExpires, и, как правило, она более полезна, если вам нужен более точный контроль над поведением кэширования.

Если эти заголовки установлены, они могут сообщить браузеру, что запрошенный файл может храниться локально в течение определенного периода времени (включая вечность), не запрашивая его снова. Если заголовки не заданы, браузеры всегда будут запрашивать файл с сервера, ожидая ответов200 OK или304 Not Modified.

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

Чтобы добавить модуль заголовка, откройте файл конфигурации Nginx по умолчанию вnano или в вашем любимом текстовом редакторе.

sudo nano /etc/nginx/sites-available/default

Найдите блок конфигурацииserver, который выглядит так:

/etc/nginx/sites-available/default

. . .
# Default server configuration
#

server {
    listen 80 default_server;
    listen [::]:80 default_server;

. . .

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

Модифицированный / etc / nginx / sites-available / default

. . .
# Default server configuration
#

# Expires map
map $sent_http_content_type $expires {
    default                    off;
    text/html                  epoch;
    text/css                   max;
    application/javascript     max;
    ~image/                    max;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    expires $expires;
. . .

Раздел перед блокомserver - это новый блокmap, который определяет соответствие между типом файла и продолжительностью кэширования этого типа файла.

Мы используем несколько различных настроек на этой карте:

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

  • Дляtext/html мы устанавливаем значениеepoch. Это специальное значение, которое явно приводит к отсутствию кэширования, что заставляет браузер всегда спрашивать, обновлен ли сам сайт.

  • Дляtext/css иapplication/javascript, которые являются таблицами стилей и файлами Javascript, мы устанавливаем значениеmax. Это означает, что браузер будет кэшировать эти файлы как можно дольше, значительно уменьшая количество запросов, учитывая, что таких файлов обычно много.

  • Последний параметр предназначен для~image/, которое является регулярным выражением, которое будет соответствовать всем типам файлов, содержащимimage/ в имениMIME type (например,image/jpg иimage/png) . Как и в случае с таблицами стилей, на веб-сайтах часто есть много изображений, которые можно безопасно кэшировать, поэтому мы также установили для этого параметра значениеmax.

Внутри блока server директиваexpires (часть модуля заголовков) устанавливает заголовки управления кешированием. Он использует значение из переменной$expires, установленной на карте. Таким образом, полученные заголовки будут отличаться в зависимости от типа файла.

Сохраните и закройте файл для выхода.

Чтобы включить новую конфигурацию, перезапустите Nginx.

sudo systemctl restart nginx

Далее, давайте удостоверимся, что наша новая конфигурация работает.

[[step-4 -—- testing-browser-caching]] == Шаг 4. Тестирование кеширования браузера

Выполните тот же запрос, что и раньше, для тестового файла HTML.

curl -I http://localhost/test.html

На этот раз ответ будет другим. Вы должны увидеть два дополнительных заголовка ответа HTTP:

Заголовки ответа Nginx

HTTP/1.1 200 OK
Server: nginx/1.10.0 (Ubuntu)
Date: Sat, 10 Sep 2016 13:48:53 GMT
Content-Type: text/html
Content-Length: 1024
Last-Modified: Sat, 10 Sep 2016 13:11:33 GMT
Connection: keep-alive
ETag: "57d40685-400"
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Cache-Control: no-cache
Accept-Ranges: bytes

ЗаголовокExpires показывает дату в прошлом, аCache-Control устанавливается с помощьюno-cache, что указывает браузеру всегда спрашивать сервер, есть ли более новая версия файла (используяETag, как и раньше).

Вы увидите разницу с файлом тестового изображения.

curl -I http://localhost/test.jpg

Заголовки ответа Nginx

HTTP/1.1 200 OK
Server: nginx/1.10.0 (Ubuntu)
Date: Sat, 10 Sep 2016 13:50:41 GMT
Content-Type: image/jpeg
Content-Length: 1024
Last-Modified: Sat, 10 Sep 2016 13:11:36 GMT
Connection: keep-alive
ETag: "57d40688-400"
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000
Accept-Ranges: bytes

В этом случаеExpires показывает дату в далеком будущем, аCache-Control содержит информациюmax-age, которая сообщает браузеру, как долго он может кэшировать файл в секундах. Это говорит браузеру, что необходимо кэшировать загруженное изображение так долго, как это возможно, поэтому любые последующие появления этого изображения будут использовать локальный кэш и вообще не отправлять запрос на сервер.

Результат должен быть одинаковым как дляtest.js, так и дляtest.css, так как файлы JavaScript и таблицы стилей также имеют кэширование заголовков.

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

Заключение

Модуль заголовков можно использовать для добавления произвольных заголовков к ответу, но правильная настройка заголовков управления кэшированием является одним из наиболее полезных приложений. Это повышает производительность для пользователей веб-сайта, особенно в сетях с более высокой задержкой, таких как сети мобильных операторов. Это также может привести к лучшим результатам в поисковых системах, которые учитывают результаты тестов скорости. Настройка заголовков кэширования в браузере является одной из основных рекомендаций инструментов тестирования Google PageSpeed.

Более подробную информацию о модуле заголовков можно найти вin Nginx’s official headers module documentation.

Related