Настройка nginx для статики

Настройка nginx для статики #

Конфигурируем nginx для статического сайта или блога

Настройка vhost и отдача статики #

Один nginx может обслуживать несколько виртуальных хостов (vhost), различая их по заголовку Host в запросе. При запросе из браузера доменное имя, такое как example.com, автоматически попадает в заголовок Host.

Пример:

server {
    listen 8080;
    listen [::]:8080;

    server_name example.com example.local localhost;

    root /app/public;

    location / {
        index index.html;
    }
}

Пояснения к примеру:

  • nginx будет прослушивать порт 8080 для протоколов IPv4 и IPv6
  • HTTPS не включён, то есть используется HTTP без TLS/SSL
  • виртуальный сервер настроен на три доменных имени: example.com, example.local, localhost
  • статика будет отдаваться для всех URL Path сайта из каталога /app/public
  • если файл, соответствующий URL Path, не найден в /app/public, то будет возвращена страница 404

Кеширование статики #

Пример:

server {
    # Другие директивы

    location ~* \.(svg|png|webp|jpg|jpeg|gif|ico) {
        expires 30d;
    }

    location ~* \.(css|js|woff|woff2|webmanifest) {
        expires 180d;
    }
}

Пояснения к примеру:

  1. Директива expires 30d; установит заголовки, чтобы браузер хранил статику 30 дней, например
    • Cache-Control: max-age=2592000
    • Expires: Sun, 11 Mar 2025 13:26:14 GMT (+30 дней от 9 февраля 2025)
  2. Кеширование включено для типовой статики:
    • изображений в форматах SVG/PNG/WEBP/JPEG/GIF/ICO — на 30 дней
    • стилей CSS, скриптов JS, шрифтов в форматах WOFF/WOFF2, файла Web App Manifest — на 180 дней
  3. Хранить можно и дольше — но не забывайте:
    • сайт меняется и его статика тоже
    • кеш клиента не безграничен и может очищаться от старых файлов

Версионирование статики #

Если кеширование есть, а версионирования статики нет, то при обновлении сайта у клиента могут «поехать» стили и сломаться JavaScript.

Версионирование статики можно вести:

  1. Автоматически — средствами генератора статического сайта
  2. Вручную — силами разработчика сайта

Популярные методы версионирования:

  • Каждый релиз сайта (движка сайта, стилей, скриптов) сопровождать номером версии и указывать номер версии в HTML
    • В префиксе URL Path: /css/v89/main.css
    • В названии файла: /css/main_v89.css
    • В Query параметре: /css/main.css?v=89
  • Использовать хеш содержимого файла и указывать его в HTML
    • В префиксе URL Path: /css/d220a4f/main.css
    • В названии файла: /css/main_d220a4f.css
    • В Query параметре: /css/main.css?v=d220a4f

Сжатие gzip #

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

Пример:

server {
    # ... другие директивы

    gzip on;
    gzip_types text/html text/css application/javascript image/svg+xml text/xml application/xml+rss;
    gzip_proxied no-cache no-store private expired auth;
    gzip_comp_level 6;
}

Пояснения к примеру:

  1. В примере включено GZIP сжатие «на лету» для HTML, CSS, JS, SVG файлов, а также для XML (например, sitemap) и XML+RSS (для RSS ленты)
  2. Директива gzip_proxied включает сжатие для клиентов, использующих proxy сервер
    • proxy часто включены в офисных компьютерах различных организаций
  3. Уровень сжатия установлен на 6

Если всё настроено верно, то в браузере в DevTools вы сможете увидеть заголовок ответа Content-Encoding: gzip.

Для каких MIME типов включать GZIP? #

Стоит сжимать все текстовые форматы: HTML, CSS, JS, SVG. Минифицированные файлы CSS/JS тоже стоит сжимать.

Нет смысла включать GZIP сжатие:

  1. Для изображений PNG, JPEG, WEBP, GIF, потому что сжатие заложено в алгоритмы кодирования изображений
    • тем не менее, можно сжать сами изображения лучше — подробности ищите по запросам «png optimizer», «jpeg optimizer»
  2. Для web шрифтов в формате WOFF и WOFF2 — в них заложено сжатие алгоритмами deflate и brotli соответственно
  3. Для видео и аудио в типовых форматах: OGG, MP3, MP4 и так далее — сжатие заложено в алгоритмы кодирования видео/аудио

Посмотреть доступные для nginx MIME типы в Linux можно командой:

cat /etc/nginx/mime.types

Использование gzip_static #

Иногда при создании сайта есть возможность заранее сжимать файлы в GZIP.

Допустим, генератор статического сайта сжимает файлы HTML/JS/CSS в GZIP архивы:

  • index.html сжимается в index.html.gz
  • js/article-toc.js сжимается в js/article-toc.js.gz

Тогда в nginx можно задействовать директиву gzip_static с тремя вариантами:

  • off (по умолчанию) — выключает поиск предварительно сжатого файла
  • on — включает поиск предварительно сжатого файла
  • always — всегда использует только предварительно сжатые файлы без проверки

Пример:

server {
    # ... другие директивы

    # Отдавать сжатый контент из файла *.gz, если он найден
    gzip_static on;

С такой конфигурацией nginx будет:

  • отдавать контент из файла *.gz, если есть файл, соответствующий URL
  • действовать обычным путём с учётом других директив gzip*, если файла *.gz нет

Сайт atdd.ru — блог разработчика.