Ниже — упорядоченный чек‑лист и типичные причины, которые нужно проверить, когда React‑приложение на сервере «висит» на белом экране и не завершает загрузку.
Быстрая проверка (выполните в первую очередь)
1. Откройте DevTools → Network, нажмите Ctrl+R (полная перезагрузка, отключите кэш), посмотрите:
- Загружаются ли все .js и .css файлы и возвращают ли они статус 200 (или 304)?
- Не возвращает ли вместо .js файл HTML (частая причина — сервер отдает index.html при запросе ассетов).
- Content‑Type и Content‑Encoding для .js: должны быть text/javascript/ application/javascript и корректный Content‑Encoding (если сжатие включено).
2. В DevTools → Console:
- Уберите фильтры (Errors, Warnings и т.д.), проверьте, нет ли синтаксических ошибок (Unexpected token <), ошибок загрузки скриптов, CSP, SRI, ошибок Service Worker.
3. Попробуйте локально: в папке build запустите serve -s build или npx serve build — если локально всё ок, значит проблема на сервере.
Типичные причины и что проверить дальше
1. Неправильная отдача статики (чаще всего)
- Сервер (nginx/Apache) настроен так, что при запросе /static/js/... возвращается index.html (200) — тогда браузер получает HTML вместо JS, и скрипты ломаются. В Network браузера это видно по содержимому ответа (начинается с <!doctype html>).
- Проверка: curl -i https://example.com/static/js/main.*.js или откройте файл в браузере — должен быть JS, а не HTML.
2. Неправильный publicPath/homepage (путь к ассетам)
- Если приложение развернуто в подпапке, а сборка предполагает корень (/), пути к ассетам будут неверные и файлы 404. Для create‑react‑app прописывайте "homepage" в package.json или настраивайте publicPath в сборщике.
- Альтернатива: используйте HashRouter вместо BrowserRouter если не хотите настраивать серверную маршрутизацию.
3. Ошибки сжатия/Content‑Encoding
- Сервер может отдавать gzip‑сжатый файл без заголовка Content‑Encoding: gzip (или наоборот декомпрессировать дважды), в результате браузер получает «мусор» и не выполняет JS, иногда без понятной ошибки.
- Проверка: смотрите заголовки ответа (curl -I) и исход содержимого.
4. CSP / SRI / CORs / политика безопасности
- Content‑Security‑Policy может блокировать выполнение inline‑скриптов или загрузку ресурсов. SRI (integrity attribute) может блокировать, если хеш не совпадает.
- Проверка: заголовки ответа на index.html, сообщения в Console о CSP/SRI.
5. Service Worker / кеширование старой версии
- Старый SW может перехватывать запросы и отдавать некорректные ресурсы.
- Проверка: DevTools → Application → Service Workers → unregister и Hard Reload.
6. Ошибки маршрутизации (React Router)
- При переходе по URL сервер должен отдавать index.html для всех SPA‑маршрутов (try_files ... /index.html). Но при неправильной конфигурации сервер может отдавать 404 или неправильный файл.
- Нужна конфигурация fallback на index.html, но при этом статику нужно отдавать корректно.
7. Неправильные MIME‑типы
- Сервер может отдавать .js как text/html. Проверить заголовок Content‑Type.
8. Файловая система и регистрозависимость
- На Windows/Dev регистр файла не важен, на Linux — важен. Неправильный импорт/имя файла может пройти на сборке, но при runtime ассеты не найдутся.
- Проверка: убедитесь, что имена файлов совпадают по регистру.
9. Ошибки маршаллинга или root‑элемент отсутствует
- index.html должен содержать <div id="root"></div> (id совпадает с тем, что использует React). Отсутствие элемента может привести к ошибкам при монтировании.
10. Скрипты блокируются политиками хоста (WAF, прокси)
- Внешние прокси или CDN могут блокировать/модифицировать скрипты.
Что конкретно сделать — шаги и команды
1. Откройте DevTools → Network → Reload (Disable cache). Просмотрите:
- Список статичных файлов (.js, .css, fonts, images) — статус, размер, тип.
- Откройте проблемный .js — если видите HTML, это подтверждение проблемы с отдачей статики.
2. Используйте curl/wget:
- curl -I https://example.com/ (проверить заголовки index.html)
- curl -I https://example.com/static/js/main.*.js
- curl -s https://example.com/static/js/main.*.js | head -n 5 (показать начало файла)
3. Посмотрите логи сервера:
- nginx: /var/log/nginx/error.log и access.log — есть ли 404/500 на статические файлы?
4. Если nginx, проверьте конфиг. Пример корректного для SPA:
- location /static/ { alias /var/www/app/build/static/; }
- location / { try_files $uri $uri/ /index.html; }
Убедитесь, что static/ и index.html корректно указывают на build.
5. Проверить Content‑Encoding:
- curl -I https://example.com/static/js/main.*.js (проверить Content-Encoding)
6. Service Worker:
- DevTools → Application → Service Workers → Unregister, затем Hard Reload.
7. Попробуйте развернуть build локально (serve -s build). Если локально всё ок — значит дело в серверной конфигурации.
8. Посмотрите на package.json: есть ли поле "homepage" (если развернуто в подпапке)? Если нет — установите или исправьте publicPath.
9. Включите source maps (если отключены) при сборке, чтобы видеть ошибки в исходном коде.
Что чаще всего помогает (решения)
- Исправить nginx/Apache конфиг, чтобы статические файлы отдавались как файлы, а не перенаправлялись на index.html.
- Установить correct Content‑Type и Content‑Encoding для JS/CSS.
- Добавить "homepage" в package.json или настроить publicPath в сборщике, или использовать HashRouter.
- Удалить/обновить Service Worker (часто после деплоя остаётся старый SW и мешает).
- Проверить и исправить CSP/SRI заголовки, если они блокируют.
Если хотите, могу помочь конкретно с проверкой — пришлите:
- URL, где это воспроизводится (если публично доступен), или
- вывод curl -I для index.html и для одного из JS-файлов, или
- ваш nginx/Apache конфиг (фрагмент, где настроены location/alias/try_files) и структуру build (например ls -la build/static/js).