Nginx try_files
try_files — одна из главных директив для статического сайта.
Она говорит Nginx: “проверь эти пути по порядку и отдай первый существующий файл”.
Для статической сборки Astro обычно нужен простой и предсказуемый вариант.
Базовый вариант
location / {
try_files $uri $uri/ =404;
}
Что делает эта строка:
- Проверяет точный путь
$uri. - Проверяет директорию
$uri/. - Если ничего не найдено — отдаёт
404.
Почему работает /ru/docs/
При trailingSlash: 'always' Astro создаёт страницы как директории с index.html:
dist/ru/docs/index.html
dist/ru/docs/cache-control/index.html
Когда пользователь открывает:
/ru/docs/cache-control/
Nginx проверяет директорию и отдаёт:
/var/www/getsrv.app/ru/docs/cache-control/index.html
Что будет с /ru/docs/cache-control
Если запрос пришёл без trailing slash:
/ru/docs/cache-control
try_files $uri $uri/ =404 сначала проверит файл /ru/docs/cache-control, потом директорию /ru/docs/cache-control/.
Если директория есть, Nginx сможет отдать index.html.
Controlled 404
Для статического сайта лучше иметь управляемую 404-страницу:
error_page 404 /404.html;
location = /404.html {
internal;
}
Тогда несуществующий путь:
curl -kI https://getsrv.app/no-such-page
вернёт:
HTTP/2 404
content-type: text/html
Это лучше, чем случайный directory listing или голая Nginx-страница.
Assets лучше проверять отдельно
Для /assets/ обычно делают отдельный location:
location /assets/ {
try_files $uri =404;
access_log off;
add_header Cache-Control "public, max-age=31536000, immutable" always;
}
Здесь не нужен $uri/, потому что assets — это конкретные файлы, а не страницы-директории.
Плохой вариант для этого сайта
location / {
try_files $uri /index.html;
}
Такой вариант часто используют для SPA. Для обычного статического справочника он хуже: несуществующие страницы могут отдавать главную с кодом 200.
Это ломает:
- нормальный
404; - sitemap/SEO;
- диагностику;
- ожидания пользователя.
Проверить конкретную страницу
sudo test -f /var/www/getsrv.app/ru/docs/cache-control/index.html && echo OK || echo missing
curl -kI https://getsrv.app/ru/docs/cache-control/
Ожидаемо:
OK
HTTP/2 200
Проверить 404
curl -kI https://getsrv.app/no-such-page
Ожидаемо:
HTTP/2 404
Проверить assets
ASSET="$(find /var/www/getsrv.app/assets -maxdepth 1 -type f | head -n 1 | sed 's#^/var/www/getsrv.app##')"
curl -kI "https://getsrv.app$ASSET"
Ожидаемо:
HTTP/2 200
Cache-Control: public, max-age=31536000, immutable
Частые ошибки
Ошибка 1. SPA fallback вместо 404
try_files $uri /index.html;
Для справочника лучше не использовать.
Ошибка 2. Нет error_page 404
Тогда разные 404 могут выглядеть непредсказуемо.
Ошибка 3. Assets проходят через общий location
Если /assets/ не выделен отдельно, к ним может примениться HTML cache policy.
Ошибка 4. Web-root смотрит не туда
Проверьте:
sudo grep -RIn "root " /etc/nginx/sites-enabled /etc/nginx/conf.d
И убедитесь, что root указывает на актуальный каталог:
/var/www/getsrv.app
Минимальный рабочий набор
root /var/www/getsrv.app;
location /assets/ {
try_files $uri =404;
add_header Cache-Control "public, max-age=31536000, immutable" always;
}
location / {
try_files $uri $uri/ =404;
add_header Cache-Control "public, must-revalidate" always;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
Для обычной статической сборки этого достаточно.