Руководства

Как исправить ошибки 404 после деплоя сайта или приложения

Если приложение работает локально, но страницы дают 404 после деплоя, чаще всего причина в отсутствии маршрутизации одностраничного приложения (SPA): сервер ищет файл /dashboard, которого нет, потому что такой маршрут существует только в JavaScript. Решение — правило, которое отдаёт index.html для маршрутов приложения. Другие причины: файлы не попали в результат сборки, пути чувствительны к регистру, слеш в конце адреса обрабатывается по-разному, неверный базовый путь или API-маршруты вообще не развёрнуты.

Начните с того, чтобы точно записать, какой URL выдаёт 404 и как вы на него попали. По этому шаблону уже видна причина.

Шаг 1: Найдите закономерность

Что вы видитеНаиболее вероятная причинаПерейти к
Главная работает, переходы по ссылкам работают, но обновление или прямая ссылка на внутреннюю страницу дают 404Нет запасного правила SPAШаг 2
Все страницы дают 404, включая главнуюОпубликована неверная папка или сборка не развернуласьШаг 3
Страницы открываются, но картинки, шрифты или скрипты дают 404Файлов нет в сборке или пути неверныШаг 4
Работает с /about/, не работает с /about (или наоборот)Обработка слеша в конце адресаШаг 5
/About не работает, а /about работаетСервер чувствителен к региструШаг 4
Страница открывается, но запросы к данным /api/... дают 404API не развёрнут или не маршрутизированШаг 6
Старые адреса с прежнего сайта дают 404Не настроены редиректыШаг 7
Только на собственном доменеНастройка DNS или доменаШаг 8

Чтобы увидеть реальный код статуса, откройте инструменты разработчика (правый клик → Inspect), перейдите на вкладку Network, перезагрузите страницу и посмотрите статус первого запроса.

Шаг 2: Добавьте запасное правило SPA

Это классический случай. В одностраничном приложении на React, Vue или Svelte на сервере есть лишь несколько настоящих файлов: index.html и немного JavaScript и CSS. Такие маршруты, как /dashboard или /projects/42, обрабатывает роутер в браузере.

  • Переход по ссылке работает: роутер меняет адрес и рисует новую страницу, не обращаясь к серверу.
  • Обновление или открытие ссылки напрямую не работает: браузер запрашивает у сервера /dashboard, файла нет, и сервер возвращает 404.

Решение — правило: если запрос не совпадает с настоящим файлом, отдать index.html со статусом 200 и передать управление роутеру. Как его добавить, зависит от хостинга (проверяйте актуальную документацию, так как детали меняются):

ХостингТипичное правило запасного маршрута
NetlifyФайл _redirects в опубликованной папке с правилом /* /index.html 200
VercelRewrite в vercel.json со всех путей на /index.html (шаблоны фреймворков часто делают это сами)
Cloudflare PagesОтдаёт фолбэк в стиле SPA по умолчанию, если нет 404.html в корне
Nginxtry_files $uri $uri/ /index.html; в блоке location /
ApacheПравило rewrite в .htaccess, которое отправляет запросы не к файлам на index.html
GitHub PagesСерверных rewrite нет; обходные пути: хеш-маршрутизация или 404.html, который делает редирект

Убедитесь, что правило не перехватывает настоящие файлы: запросы к /assets/app.js должны по-прежнему возвращать JavaScript-файл. Если вместо него приходит index.html, вы получите пустую страницу с ошибкой «Failed to load module script». См. как исправить белую страницу.

Также задайте роутеру маршрут-заглушку, чтобы адреса, которые не совпадают ни с одной страницей, показывали понятное сообщение «Страница не найдена», а не пустоту.

Если изменить настройки сервера нельзя, хеш-маршрутизация (адреса вида /#/dashboard) обходит проблему, потому что часть адреса после # никогда не отправляется серверу. Это обходной путь, а не первый выбор: адреса выглядят хуже и хуже индексируются поисковиками.

Фреймворки, которые отрисовывают страницы на сервере или генерируют их при сборке (Next.js, Astro и подобные), обычно имеют настоящие файлы или серверные маршруты для каждой страницы, поэтому эта проблема там встречается реже. Их аналог — страница, которую не сгенерировали при сборке.

Шаг 3: Проверьте, что именно развёрнуто

Если всё дает 404, сервер, скорее всего, не отдаёт собранное приложение.

  • Правильная папка. Хостинг должен публиковать результат сборки (обычно dist для Vite, build для Create React App, out для статического экспорта Next.js), а не корень проекта.
  • Сборка выполнилась. Прочитайте лог деплоя. Если сборка упала, хостинг мог развернуть ничего или старую версию.
  • index.html лежит в корне опубликованной папки, а не во вложенной.
  • Базовый путь совпадает. Если приложение открывается по адресу example.com/app/, его нужно собрать с этим базовым путём (base в Vite, basename в React Router), иначе все маршруты и файлы промахнутся.

Шаг 4: Исправьте отсутствующие файлы и неверные пути

Если страницы открываются, но ресурсы дают 404:

  • Регистр букв. На macOS и Windows Logo.png и logo.png обычно считаются одним файлом. Большинство Linux-серверов так не делают. Каждая ссылка должна точно совпадать с именем файла.
  • Файлы вне сборки. В Vite файлы из public/ копируются как есть и подключаются от корня (/logo.png). Файлы, которые импортируются в коде, включаются в сборку. Файл, лежащий в другом месте проекта, может вообще не развернуться.
  • Относительные пути. images/photo.jpg вычисляется относительно текущего адреса, поэтому ломается на /blog/post-1. Используйте /images/photo.jpg.
  • Загруженные файлы, сохранённые на локальный диск. Если загрузки пользователей записывались в папку на сервере, они пропадут при развёртывании новой версии. Используйте нормальное файловое хранилище.

Шаг 5: Последовательно обрабатывайте слеш в конце адреса

/about и /about/ — разные адреса. Хостинги по-разному добавляют или убирают слеш, и несоответствие ссылок или роутера может давать 404 или бесконечные редиректы. Выберите один стиль, сделайте ссылки такими же и настройте хостинг, чтобы он перенаправлял другой вариант на выбранный. Единообразие помогает и поисковикам, которые иначе могут видеть две копии каждой страницы.

Шаг 6: Исправьте API-маршруты, которые дают 404

Если страница открывается, но во вкладке Network запросы /api/... возвращают 404:

  • Бэкенд не развёрнут. Статический хостинг отдаёт только файлы; бэкенд должен работать где-то.
  • В продакшене путь маршрутизируется иначе. В разработке прокси мог перенаправлять /api на отдельный сервер. В продакшене хостингу нужен аналогичный rewrite, либо фронтенд должен обращаться к реальному адресу API.
  • Запасное правило SPA перехватило запрос. Если запрос к API возвращает index.html со статусом 200, правило слишком широкое. Исключите /api/* из него.

Запросы опубликованного приложения к /api/orders возвращают 404, хотя в предпросмотре работают. Сравни, как /api маршрутизируется в предпросмотре и в опубликованном приложении, и сделай так, чтобы опубликованный фронтенд обращался к бэкенду тем же способом.

Шаг 7: Настройте редиректы со старых адресов

Если вы переехали с другого сайта или перестроили структуру, старые адреса, которыми пользуются люди и поисковики, будут давать 404. Добавьте постоянный редирект 301 с каждого старого адреса на новый. Составьте список и проверьте выборку после запуска. Наше руководство по переносу сайта на WordPress описывает, как составить такой список.

Шаг 8: Проверьте домен

Если приложение работает по адресу хостинга, но на вашем домене выдаёт 404, домен может указывать на другой проект или хостинг ещё не подключил его к вашему сайту. Проверьте записи DNS и настройки доменов на хостинге. См. как подключить собственный домен.

Сделайте настоящую страницу 404 полезной

Некоторые 404 корректны: человек опечатался в адресе. Сделайте такую страницу полезной:

  • Короткое сообщение и ссылки на главную и ключевые разделы
  • Поле поиска, если на сайте есть поиск
  • Та же шапка и навигация, что и на остальном сайте

Там, где это позволяет настройка, возвращайте настоящий статус 404 для несуществующих страниц. Сообщение «не найдено» со статусом 200 поисковики называют мягкой ошибкой 404: она тратит их время обхода и путает индексацию.

Частые ошибки

  • Проверка только кликами. Всегда проверяйте, вставляя глубокие адреса в новую вкладку и обновляя страницу.
  • Правило, которое перехватывает всё. Ресурсы и API-маршруты возвращают index.html, что вызывает пустые страницы и запутанные ошибки API.
  • Разный регистр в именах, который ломается только на сервере.
  • Развёртывание папки с исходниками вместо результата сборки.
  • Перестройка адресов без редиректов. Каждая старая ссылка превращается в 404.

404 в Mythex

В Mythex вы публикуете проект из рабочего пространства, а статические фронтенды развёртываются как статические сайты. Если опубликованная страница дает 404, передайте агенту точный адрес, скажите, возникает ли ошибка при обновлении или при переходе по ссылке, и что показывает вкладка Network, и попросите проверить маршрутизацию. После исправления опубликуйте проект заново: живое приложение остаётся снимком до следующей публикации. Если вы недавно меняли проект, а сайт выглядит устаревшим, опубликуйте снова и обновите страницу жёстким обновлением. Если сборка падает, используйте Fix with AI в окне публикации. См. How to publish и Publish troubleshooting в документации, а также наше руководство по отладке приложения, созданного с ИИ.

Чек-лист по 404

  • Записано, какие адреса дают 404 и при клике, при обновлении или в обоих случаях
  • Запасное правило SPA отдаёт index.html для маршрутов приложения со статусом 200
  • Правило не затрагивает настоящие файлы и /api/*
  • В роутере есть маршрут-заглушка «не найдено»
  • Опубликована папка с результатом сборки, и сборка прошла успешно
  • Базовый путь совпадает с местом, где открывается приложение
  • Регистр имён файлов совпадает с каждой ссылкой
  • Пути к ресурсам начинаются с /
  • Стиль слеша в конце адреса единообразен
  • API-маршруты развёрнуты и маршрутизированы в продакшене
  • Для старых адресов настроены редиректы 301
  • Глубокие ссылки проверены вставкой в новую вкладку

Вопросы

Почему при обновлении страницы в моём React-приложении появляется 404?

В одностраничном приложении такие маршруты, как /dashboard, существуют только в JavaScript. Переход по ссылке работает, потому что роутер обрабатывает его в браузере, а при обновлении браузер запрашивает у сервера файл /dashboard, которого нет. Решение — правило, которое отдаёт index.html для маршрутов приложения.

Как добавить запасной маршрут SPA на Netlify, Vercel или Nginx?

На Netlify добавьте файл _redirects с правилом /* /index.html 200. На Vercel добавьте rewrite в vercel.json, который отправляет все пути на /index.html. В Nginx используйте try_files $uri $uri/ /index.html; в блоке location. Проверяйте документацию хостинга, так как правила меняются.

Почему мои картинки или файлы дают 404 после деплоя?

Обычно файл не попал в результат сборки, регистр букв в пути не совпадает (серверы часто различают регистр, а ноутбук — нет), либо путь относительный там, где должен начинаться с косой черты.

Должна ли страница, которой нет, возвращать настоящий статус 404?

Да. Показывайте полезную страницу «не найдено», но со статусом 404, если это позволяет ваша настройка. Поисковые системы считают сообщение «не найдено», отданное со статусом 200, мягкой ошибкой 404: это тратит время обхода и путает индексацию.

Mythex · Pricing · Создавайте что угодно с ИИ · Шаблоны сайтов и приложений · Сравнения Mythex · Глоссарий по созданию приложений с ИИ · Бесплатные инструменты для создания приложений с ИИ · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)