Настройка кэширования браузера в Nginx с помощью модуля header в CentOS 7

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

Ускорить загрузку сайта можно разными способами, и кэширование браузера – один из самых важных. Это позволяет браузеру повторно использовать локальные копии загруженных ранее файлов. Для этого необходимо ввести новые заголовки ответа HTTP.

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

Требования

  • Сервер CentOS 7 (о настройке сервера можно узнать здесь).
  • Пользователь с доступом к команде sudo.
  • Предварительно установленный веб-сервер Nginx (руководство по установке – здесь).
  • Модуль map (инструкции по настройке этого модуля – в этой статье).

1: Создание тестовых файлов

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

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

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

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

sudo truncate -s 1k /usr/share/nginx/html/test.html

Таким же образом создайте ещё несколько тестовых файлов с расширениями jpg (изображение), css (таблица стилей) и js (JavaScript):

sudo truncate -s 1k /usr/share/nginx/html/test.jpg
sudo truncate -s 1k /usr/share/nginx/html/test.css
sudo truncate -s 1k /usr/share/nginx/html/test.js

2: Проверка стандартного поведения Nginx

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

Отправьте запрос к test.html с локального сервера Nginx и просмотрите заголовки ответа:

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

Эта команда вернёт такой заголовок:

HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Thu, 06 Oct 2016 10:21:04 GMT
Content-Type: text/html
Content-Length: 1024
Last-Modified: Thu, 06 Oct 2016 10:20:44 GMT
Connection: keep-alive
ETag: "57f6257c-400"
Accept-Ranges: bytes

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

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

Вы можете симулировать это поведение с помощью следующей команды:

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

Примечание: Укажите своё значение ETag вместо 57f6257c-400.

Теперь вывод будет таким:

HTTP/1.1 304 Not Modified
Server: nginx/1.10.1
Date: Thu, 06 Oct 2016 10:21:40 GMT
Last-Modified: Thu, 06 Oct 2016 10:20:44 GMT
Connection: keep-alive
ETag: "57f6257c-400"

В этот раз Nginx вернет 304 Not Modified. Веб-сервер не будет пересылать файл снова, он просто сообщит браузеру о том, что он может повторно использовать загруженный ранее файл.

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

3: Настройка заголовков Cache-Control и Expires

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

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

Эти HTTP-заголовки можно настроить с помощью модуля header. Модуль Header встроен в Nginx, а значит, его не нужно устанавливать.

Чтобы добавить этот модуль, откройте файл виртуального хоста Nginx по умолчанию в текстовом редакторе:

sudo vi /etc/nginx/nginx.conf

Читайте также: Установка и использование текстового редактора Vim

Найдите блок server:

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

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

. . .
# 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/ – регулярное выражение, которое ищет все файлы с MIME-типом image/ (например, image/jpg и image/png). Оно также имеет значение max, поскольку изображений, как и таблиц стилей, на сайтах много. Кэшируя их, браузер уменьшит количество запросов.

Директива expires (включена в модуль headers) настраивает заголовки для управления кэшированием. Она использует значение переменной $expires, указанной в блоке map, благодаря чему заголовки ответа отличаются в зависимости от типа файла.

Сохраните и закройте файл.

Чтобы обновить настройки, перезапустите Nginx:

sudo systemctl restart nginx

4: Тестирование кэширования браузера

Выполните тот же запрос, что и в начале руководства:

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

Время ответа будет отличаться. В выводе вы увидите два новых заголовка ответа HTTP:

HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Thu, 06 Oct 2016 10:24:42 GMT
Content-Type: text/html
Content-Length: 1024
Last-Modified: Thu, 06 Oct 2016 10:20:44 GMT
Connection: keep-alive
ETag: "57f6257c-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
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Thu, 06 Oct 2016 10:25:02 GMT
Content-Type: image/jpeg
Content-Length: 1024
Last-Modified: Thu, 06 Oct 2016 10:20:46 GMT
Connection: keep-alive
ETag: "57f6257e-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, вы должны получить похожий результат.

Из вывода команды curl видно, что кэширование браузера успешно настроено. Кэширование страниц увеличит производительность сайта и уменьшит количество запросов.

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

Читайте также: Официальная документация модуля headers.

Tags: , , ,

Добавить комментарий