Вы создали красивое React-приложение с клиентской маршрутизацией, собрали его в аккуратные статические файлы, но при обновлении страницы или прямом переходе по URL получаете предательскую ошибку 404. Знакомая ситуация? Это классическая проблема одностраничных приложений (SPA), и решается она правильной настройкой веб-сервера. В этой статье мы разберем, как настроить Nginx для безупречной работы с React Router, чтобы ваше приложение вело себя как полноценный сайт, а не как набор отдельных страниц.
Почему React Router и Nginx конфликтуют?
React Router — это клиентский маршрутизатор. Он управляет отображением компонентов, манипулируя историей браузера, но не создает физических файлов для каждого маршрута в папке сборки. Когда вы переходите по прямому URL (например, /dashboard/profile), Nginx ищет соответствующую папку или файл на сервере, не находит его и возвращает 404. Нам нужно научить Nginx перенаправлять все подобные запросы на единственный точку входа — index.html.
Базовая конфигурация Nginx для SPA
Вот минимальная рабочая конфигурация для сервера блоков (обычно находится в /etc/nginx/sites-available/your-site или аналогичном месте).
server {
listen 80;
server_name your-domain.com;
root /var/www/your-react-app/build;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
Разбираем ключевую директиву
Волшебство происходит в блоке location / с директивой try_files.
- $uri: Nginx сначала проверяет, существует ли файл, точно соответствующий запрошенному URL (например,
/static/js/main.js). - $uri/: Затем проверяет, существует ли папка с таким именем.
- /index.html: Если оба предыдущих условия не выполнены, сервер отдает файл
index.html. React Router, загрузившись, проанализирует URL в адресной строке и отобразит нужный компонент.
Эта конфигурация идеально подходит для приложений, развернутых в корне домена. Если ваше приложение находится в поддиректории (например, https://site.com/app/), вам потребуется дополнительная настройка базового пути (basename) в React Router и соответствующая правка в конфиге Nginx.
Продвинутые настройки и оптимизация
Кэширование статических ассетов
Файлы в папке build/static имеют хэши в именах, что позволяет агрессивно их кэшировать. Добавьте этот блок в конфигурацию:
location /static/ {
expires 1y;
add_header Cache-Control \"public, immutable\";
}
Обработка ошибок
Чтобы даже страницы ошибок (404, 500) обрабатывались вашим React-приложением (где вы можете показать красивый кастомный компонент), перенаправляйте их на index.html:
error_page 404 /index.html;
error_page 500 502 503 504 /index.html;
Поддержка HTML5 History API и чистых URL
Если вы используете createBrowserHistory() (стандарт для React Router v6) и хотите убрать # из URL, приведенная выше базовая конфигурация уже это обеспечивает. Главное — убедиться, что в package.json перед сборкой указано правильное поле \"homepage\", если приложение размещено не в корне.
После любых изменений в конфигурационных файлах Nginx не забудьте проверить синтаксис командой sudo nginx -t и перезагрузить сервер: sudo systemctl reload nginx.
Частые проблемы и их решение
- Белый экран после деплоя. Проверьте, что путь в директиве
rootведет к папкеbuildвашего проекта и права доступа корректны. - Статические файлы (CSS, JS) не загружаются. Убедитесь, что блок
location /static/не конфликтует с основной директивойlocation /. Статические файлы должны отдаваться как физические файлы, а не перенаправляться на index.html. - Маршруты работают, но только после первой загрузки. Это ожидаемое поведение SPA. Весь код загружается при первом запросе, далее маршрутизация происходит на клиенте.
FAQ (Часто задаваемые вопросы)
Нужен ли Node.js сервер для React приложения?
Нет, для статического React-приложения (собранного командой npm run build) достаточно любого веб-сервера, способного раздавать статические файлы, например, Nginx или Apache. Node.js требуется только для серверного рендеринга (SSR).
Почему try_files работает, а rewrite нет?
Директива try_files более эффективна и безопасна для этой задачи. Она проверяет существование файлов в указанном порядке, в то время как rewrite выполняет перенаправление, что может быть избыточно.
Как настроить для приложения в поддиректории?
1. В React Router задайте basename: <BrowserRouter basename=\"/app\">.
2. В конфиге Nginx измените root на путь к папке build и настройте location: location /app { try_files $uri $uri/ /app/index.html; }
Работает ли эта настройка с React Router v6?
Да, абсолютно. Принцип работы клиентского маршрутизатора не изменился. Конфигурация Nginx универсальна для любого SPA, будь то React, Vue или Angular с их роутерами.