Настройка Nginx для статических сайтов и SPA
Практика3 минРедакция Innovialabs
Коротко
Для SPA в Nginx достаточно указать root с собранными файлами и try_files $uri $uri/ /index.html, а хешированным ассетам отдать долгий кеш, при этом index.html не кешировать.
Короткий ответ
Статический сайт или SPA (React, Vue, Angular, Svelte) после сборки — это папка с index.html, JS, CSS и картинками. Nginx отдаёт их напрямую с диска, без backend. Для SPA нужна одна важная деталь: fallback на index.html, чтобы прямые ссылки вида /profile/settings не возвращали 404.
Базовый server-блок для SPA
server {
listen 80;
server_name app.example.com;
root /var/www/app/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
try_files проверяет варианты по порядку: существует ли файл, существует ли папка, и если ничего не найдено — отдаёт /index.html. Дальше маршрут обрабатывает роутер приложения в браузере.
Кеширование ассетов
Сборщики (Vite, webpack и другие) добавляют в имена файлов хеш содержимого: app.3f9a1c.js. Если файл изменится, изменится и имя. Значит, такие файлы можно кешировать надолго, а index.html — нет, иначе пользователи не увидят новую версию.
server {
listen 80;
server_name app.example.com;
root /var/www/app/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /assets/ {
try_files $uri =404;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location = /index.html {
add_header Cache-Control "no-cache";
}
}
| Тип файла | Политика кеша |
|---|---|
| Хешированные JS, CSS, шрифты | Долгий кеш, immutable |
index.html | no-cache — браузер перепроверяет каждый раз |
| Картинки без хеша в имени | Умеренный кеш или хеш в имени |
Обратите внимание на try_files $uri =404 в /assets/: отсутствующий JS-файл должен давать честную 404, а не index.html с кодом 200. Иначе браузер получит HTML вместо скрипта и выдаст непонятную ошибку.
Путь /assets/ зависит от сборщика — проверьте, куда он кладёт файлы.
Многостраничный статический сайт
Для сайта, где каждая страница — отдельный HTML-файл (генераторы статики, лендинги), fallback на index.html не нужен. Вместо него — поддержка адресов без расширения и своя страница 404:
server {
listen 80;
server_name example.com;
root /var/www/site;
index index.html;
location / {
try_files $uri $uri.html $uri/ =404;
}
error_page 404 /404.html;
}
Несколько сайтов на одном сервере
Nginx выбирает блок по заголовку Host и директиве server_name. Каждому сайту — свой файл:
/etc/nginx/sites-available/app.example.comсо ссылкой вsites-enabled, или/etc/nginx/conf.d/app.example.com.conf— в зависимости от дистрибутива.
Каждый файл содержит свой server с собственными server_name и root. Чтобы запросы на неизвестные домены не попадали на случайный сайт, задайте отдельный блок с listen 80 default_server; и return 444;.
Частые ошибки
- Нет fallback для SPA. Главная работает, а обновление страницы на
/dashboardдаёт 404. - Долгий кеш на index.html. После деплоя пользователи видят старую версию, пока не почистят кеш.
- Потерянные заголовки.
add_headerвнутри location отменяет всеadd_headerуровня server. Если на уровне server заданы заголовки безопасности, повторите их в location или вынесите в общий include. - Неверные права. Пользователь, под которым работает Nginx, должен иметь доступ на чтение к папке сайта.
- Применение без проверки. Всегда запускайте
nginx -tпередsystemctl reload nginx.