К основному содержимому

Отдача статики в Nginx: try_files, expires и sendfile

Nginx · 29.09.2026

Почему статику лучше отдавать напрямую

Картинки, CSS, JS и шрифты не требуют выполнения PHP-кода, поэтому пропускать их через PHP-FPM — трата ресурсов. Nginx умеет отдавать файлы с диска напрямую, в разы быстрее и с меньшей нагрузкой на сервер. Задача администратора — правильно указать Nginx, какие пути обслуживать напрямую, а какие передавать бэкенду.

Как работает try_files

Директива try_files проверяет файлы и каталоги по порядку и отдаёт первый найденный, а если ничего не найдено — передаёт запрос дальше:

location / {
    root /var/www/example.com/public;
    try_files $uri $uri/ /index.php?$query_string;
}

Здесь Nginx сначала ищет файл с точным именем запроса, потом каталог с таким именем, и только если ничего не нашлось — передаёт запрос в index.php. Это стандартная схема для WordPress, Laravel и большинства современных PHP-приложений.

Как отдавать статику отдельным location

Для статических файлов имеет смысл выделить отдельный блок с собственными настройками кэширования:

location ~* \.(jpg|jpeg|png|gif|webp|svg|css|js|woff2?)$ {
    root /var/www/example.com/public;
    try_files $uri =404;
    expires 30d;
    add_header Cache-Control "public, immutable";
    access_log off;
}

Параметр access_log off для статики снижает нагрузку на диск: незачем писать в лог тысячи запросов картинок и скриптов.

Директивы кэширования и производительности

ДирективаЗначениеЭффект
expires30d, 1yЗаголовок Cache-Control и Expires для браузера
sendfileonОтдача файла через системный вызов sendfile, без копирования в память Nginx
tcp_nopushonОтправка заголовков и начала файла одним TCP-пакетом
open_file_cachemax=1000 inactive=20sКэш дескрипторов файлов и метаданных, чтобы не читать диск повторно

Директивы sendfile и tcp_nopush включают в секции http {} один раз — они действуют глобально и не требуют настройки на каждый сайт.

Как настроить open_file_cache

На сайтах с большим числом мелких файлов — иконки, аватары, миниатюры — полезно включить кэш дескрипторов:

open_file_cache max=2000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

Это уменьшает число системных вызовов open() и stat() для файлов, которые запрашивают часто: Nginx хранит их дескрипторы в памяти вместо повторного чтения с диска.

Частые ошибки при отдаче статики

Что чаще всего ломает раздачу статики:

  • слишком долгий expires для файлов без версионирования в имени — обновлённый CSS не долетит до пользователя
  • регулярное выражение в location без экранирования точки — совпадёт с лишними путями
  • отсутствие try_files $uri =404; — запрос на несуществующий файл уйдёт в PHP-FPM зря
  • root, указанный в двух разных местах конфигурации с разными путями — типичная причина 404 на статике

Итог

Чек-лист для быстрой отдачи статики:

  • вынести статические расширения в отдельный location с try_files $uri =404;
  • задать expires от 30 дней и Cache-Control: immutable для файлов с версией в имени
  • включить sendfile, tcp_nopush и open_file_cache в http {}
  • отключить access_log для статики, чтобы не грузить диск

После настройки статики стоит проверить сжатие ответов через gzip и Brotli и включить поддержку HTTP/2 и HTTP/3 — вместе с try_files и expires это даёт основной прирост скорости сайта.

← Назад в базу знаний Задать вопрос поддержке