Чому статику краще віддавати напряму
Картинки, 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 для статики знижує навантаження на диск: немає сенсу писати в лог тисячі запитів картинок і скриптів.
Директиви кешування та швидкодії
| Директива | Значення | Ефект |
|---|---|---|
| expires | 30d, 1y | Заголовок Cache-Control і Expires для браузера |
| sendfile | on | Віддача файлу через системний виклик sendfile, без копіювання в пам'ять Nginx |
| tcp_nopush | on | Надсилання заголовків і початку файлу одним TCP-пакетом |
| open_file_cache | max=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 це дає основний приріст швидкості сайту.