Как устроен React-сайт на Vite: от исходников до готового HTML
React-сайт на Vite проходит несколько отдельных этапов: исходный код компонентов и маршрутов собирается в производственные JavaScript- и CSS-файлы, статические ресурсы копируются или обрабатываются сборщиком, а результат помещается в каталог dist, который затем передаётся веб-серверу или платформе статического хостинга. Команда vite build создаёт производственную сборку на основе index.html; путь публикации задаётся параметром base, а предварительный просмотр через vite preview предназначен для локальной проверки, а не для работы в продакшене. Для публичного React-сайта этого недостаточно само по себе: если страницы должны индексироваться, нужно отдельно определить маршруты, способ формирования HTML, обработку прямых запросов, метаданные, внутренние ссылки и правила деплоя.
Что входит в React-сайт на Vite
Vite отвечает за инструменты разработки и сборки. В проекте обычно есть исходные файлы React-компонентов, точка входа приложения, таблицы стилей, изображения, шрифты, конфигурация Vite и файл package.json со сценариями запуска. Во время разработки Vite запускает локальный сервер и обеспечивает быструю замену модулей без полной пересборки приложения. Производственная сборка выполняется отдельно и создаёт файлы, пригодные для публикации.
React отвечает за пользовательский интерфейс и состояние приложения. Он не определяет сам по себе, где будет размещён сайт, каким образом сервер обработает URL и будет ли HTML страницы сформирован заранее. Для маршрутов может использоваться React Router, но маршрутизация в браузере и обработка адресов на сервере остаются связанными задачами.
Упрощённо цепочка выглядит так:
исходники → сборка Vite → каталог dist → сервер или статический хостинг → ответ браузеру.
Если используется предварительный рендеринг или серверный рендеринг, между сборкой и выдачей страницы появляется дополнительный этап формирования HTML для конкретных маршрутов.
Структура проекта
Минимальный проект обычно содержит несколько групп файлов. Точные имена зависят от шаблона, но назначение элементов остаётся похожим.
index.html— исходный HTML-шаблон и точка входа для клиентской сборки Vite.src— исходный код приложения: компоненты, маршруты, стили, данные и функции.public— файлы, которые должны попасть в итоговую сборку без обработки импортами.vite.config.js,vite.config.tsили аналогичный файл — настройки Vite.package.json— зависимости и команды проекта.dist— результат производственной сборки.
Файлы внутри src обычно подключаются через JavaScript или TypeScript. Vite анализирует эти зависимости, обрабатывает модули и формирует итоговые ресурсы. Файлы из public используются по своим публичным адресам и не проходят такую же обработку, как импортируемые ресурсы.
В package.json проекта, созданного стандартным шаблоном Vite, обычно присутствуют команды разработки, сборки и локального просмотра результата. Названия могут отличаться, но распространённая схема выглядит так:
npm run devзапускает сервер разработки;npm run buildсоздаёт производственную сборку;npm run previewзапускает локальный просмотр уже собранного приложения.
Команда просмотра помогает проверить содержимое dist, но не заменяет настоящий веб-сервер и не предназначена для продакшен-размещения.
Как работает сборка
При выполнении vite build Vite использует корень проекта и берёт index.html как входной документ по умолчанию. Из него определяется точка подключения приложения и связанные ресурсы. Затем сборщик обрабатывает импортированные модули, стили и ассеты, формирует производственные файлы и помещает их в каталог dist, если другой каталог не задан конфигурацией.
Сборка отличается от запуска разработки. В режиме разработки браузер получает модули через сервер Vite, а изменения применяются быстро. В производственном режиме исходная структура проекта преобразуется в набор файлов, который должен быть доступен веб-серверу без участия dev-сервера.
После завершения сборки нужно проверить, что команда действительно завершилась без ошибок и что в dist появились ожидаемые файлы. Отсутствие ошибок сборщика ещё не доказывает, что сайт корректно работает на сервере. Отдельно проверяются адрес публикации, пути к ресурсам, маршруты, HTML, формы и поведение при прямой загрузке вложенного URL.
Точка входа и готовый HTML
В обычном клиентском приложении Vite собирает index.html, в который подключается JavaScript-бандл приложения. Браузер получает этот документ, загружает скрипты, запускает React и формирует интерфейс на стороне клиента. Такой подход подходит для приложений, где основное содержание появляется после выполнения JavaScript, но для публичных SEO-страниц он требует отдельной проверки доступности контента.
Если важные заголовки, основной текст, ссылки и метаданные создаются только после запуска JavaScript, исходный HTML может не содержать необходимой информации. Для сайта услуг и блога желательно, чтобы публичные страницы отдавали основной текст и важные метаданные в исходном документе. Это можно реализовать статической генерацией, предварительным рендерингом или серверным рендерингом.
Готовый HTML нужно проверять отдельно от DOM, который браузер построил после выполнения JavaScript. View Source показывает исходный документ, пришедший от сервера. Инструменты разработчика показывают текущее состояние DOM после работы приложения. Для SEO эти два состояния могут различаться, поэтому проверка только видимого экрана недостаточна.
Ресурсы и каталог dist
Производственная сборка содержит HTML, JavaScript, CSS и другие файлы, необходимые браузеру. Названия ресурсов могут включать хеши, позволяющие отличать новую версию файла от старой. Такой подход используется вместе с кешированием: изменившийся файл получает другое имя, а неизменившийся может оставаться в кеше.
Пути к ресурсам зависят от значения base. При публикации в корне домена обычно используется путь /. При размещении приложения внутри подпути, например /project/, базовый путь должен соответствовать этому адресу. Если base настроен неправильно, HTML может загрузиться, но браузер не найдёт JavaScript, CSS или изображения.
Проверка ресурсов после сборки включает несколько действий:
- открыть итоговый сайт и посмотреть ошибки загрузки в консоли;
- проверить вкладку Network и убедиться, что JavaScript и CSS возвращают успешные ответы;
- проверить пути к изображениям, шрифтам и файлам из
public; - открыть сайт из корня и из вложенного URL;
- проверить, не формируются ли адреса ресурсов относительно ошибочного пути.
Параметр base не исправляет серверную маршрутизацию. Он задаёт публичный путь к ресурсам и ссылкам, но не создаёт обработчик для URL страниц.
Маршруты и прямой запрос
Клиентский маршрутизатор может менять содержимое приложения без полной загрузки документа. После перехода с главной страницы пользователь видит нужный экран, однако прямой запрос к адресу проходит через веб-сервер. Если сервер не знает этот маршрут, он может вернуть ошибку, главную страницу или другой документ.
Для каждого публичного маршрута нужно определить:
- постоянный URL;
- компонент или страницу, которые должны быть показаны;
- данные, необходимые для страницы;
- HTML, который получает поисковый робот и пользователь;
- HTTP-статус существующего и отсутствующего адреса;
- title, description, H1 и canonical;
- ссылки на страницу из других разделов.
Статический хостинг часто использует fallback на один HTML-файл для клиентского приложения. Это позволяет приложению перехватить вложенный адрес после загрузки JavaScript, но универсальная выдача главной страницы для любого неизвестного пути может создавать soft 404. Если URL не существует, сайт должен уметь сообщить об этом корректным HTTP-ответом или применить архитектуру, в которой ошибка определяется до выдачи результата.
Прямой запрос к существующему URL, перезагрузка вложенной страницы, открытие ссылки в новой вкладке и переход назад должны проверяться отдельно. Работа навигации после перехода с главной страницы не гарантирует корректную работу прямого запроса.
Статический деплой
Для стандартной клиентской сборки Vite результатом является каталог dist. Его можно разместить на платформе статического хостинга или передать веб-серверу. Перед публикацией выполняется команда сборки, затем именно содержимое dist указывается как каталог публикации.
На GitHub Pages Vite рекомендует использовать GitHub Actions, поскольку перед размещением нужно выполнить сборку. Для сайта в корне домена базовый путь обычно равен /. Для сайта, размещённого по адресу с именем репозитория, требуется указать соответствующий подпуть в base.
Статический деплой имеет важное ограничение: сервер не выполняет React-код для каждого запроса. Он отдаёт заранее созданные файлы. Поэтому все страницы, которые должны быть доступны как самостоятельные HTML-документы, должны быть заранее сгенерированы либо сервер должен иметь правила обработки маршрутов.
При размещении на собственном сервере нужно настроить раздачу статических файлов, HTTPS, кеширование и обработку неизвестных адресов. Конкретная конфигурация зависит от веб-сервера. Важно не подменять проверку маршрутов безусловным fallback, если это приводит к возврату главной страницы со статусом 200 для несуществующего URL.
Предварительный рендеринг
Предварительный рендеринг формирует HTML для выбранных маршрутов на этапе сборки. В отличие от обычного CSR, поисковый робот получает не только пустой корневой контейнер, но и заранее подготовленное содержание страницы. После загрузки JavaScript React может подключить интерактивность и продолжить клиентскую навигацию.
Предварительный рендеринг подходит для страниц, список которых можно определить на этапе сборки. Это могут быть главная страница, услуги, статьи, контакты и другие публичные маршруты. Для каждого адреса сборочный процесс должен получить данные и записать результат в структуру, которую сможет отдать хостинг.
У предварительного рендеринга есть ограничения:
- новые страницы требуют повторной сборки или отдельного механизма публикации;
- большое количество маршрутов увеличивает время сборки;
- данные, которые меняются при каждом запросе, нельзя считать постоянными без обновления;
- ошибки получения данных должны обрабатываться на этапе сборки;
- список маршрутов должен быть полным, иначе часть страниц не будет создана.
React Router поддерживает статическое предварительное создание маршрутов в режиме, где для списка URL генерируется статический HTML и данные клиентской навигации. Такой режим предназначен для случаев, когда серверный рендеринг не используется, но отдельные публичные страницы должны быть подготовлены заранее.
Серверный рендеринг
При серверном рендеринге HTML формируется сервером во время запроса. Клиентская сборка и серверная сборка являются отдельными результатами. Vite описывает для SSR последовательность, в которой создаётся обычная клиентская сборка и отдельная SSR-сборка с серверной точкой входа.
SSR нужен, когда содержимое зависит от запроса, пользователя, актуальных данных или серверной логики. Он требует среды, которая умеет выполнять серверный код и возвращать сформированный HTML. Для простого стабильного сайта услуг SSR может быть избыточным, если страницы можно собрать заранее.
Выбор между CSR, предварительным рендерингом и SSR определяется не названием React или Vite, а требованиями проекта. Важны изменяемость данных, количество маршрутов, наличие серверной среды, требования к времени сборки и необходимость отдавать содержание до запуска JavaScript.
| Подход | Где формируется HTML | Что требуется при публикации | Подходящий сценарий |
|---|---|---|---|
| CSR | В браузере после загрузки JavaScript | Статические ресурсы и корректная обработка маршрутов | Интерактивное приложение, закрытый кабинет |
| Предварительный рендеринг | На этапе сборки | Список маршрутов и повторная сборка при изменениях | Публичные стабильные страницы и блог |
| SSR | На сервере при запросе | Среда для выполнения серверного кода | Часто меняющиеся данные и серверная логика |
Гидратация после HTML
Если сервер или сборщик заранее сформировал HTML, React должен подключить к нему клиентскую логику. Этот процесс называется гидратацией. Первый клиентский рендер должен соответствовать HTML, который был отправлен пользователю.
Несовпадения возникают, когда сервер и браузер используют разные данные, текущее время, случайные значения, локаль, состояние хранилища или браузерные API во время первоначального рендера. Ошибка гидратации может привести к повторной отрисовке части дерева и различию между первоначальным содержанием и итоговым экраном.
Критически важный текст страницы, H1, ссылки и метаданные не следует строить на случайных или доступных только в браузере значениях. Клиентские изменения, которые действительно не могут быть известны на сервере, нужно выполнять после начальной гидратации и проверять отдельно.
Контент и метаданные
Для каждой индексируемой страницы должны быть определены собственные title, description, H1, основной текст и canonical. Значения должны соответствовать текущему маршруту, а не оставаться от предыдущей страницы после клиентского перехода.
При публикации через Vite важно решить, где формируются эти данные. В чистом CSR они могут появляться после выполнения JavaScript. При предварительном или серверном рендеринге их можно включить в HTML конкретного маршрута. Проверять следует исходный ответ, а не только визуальный результат в браузере.
Основной текст не должен быть скрыт за обязательным действием пользователя, если он нужен для понимания страницы и поисковой индексации. Интерактивные формы, калькуляторы, фильтры и раскрывающиеся блоки могут дополнять страницу, но не должны быть единственным способом получить её смысл.
Деплой через GitHub
GitHub может хранить исходный код и запускать автоматическую сборку через GitHub Actions. Типовой процесс состоит из получения репозитория, установки зависимостей, запуска производственной сборки и публикации каталога dist.
В рабочем процессе нужно зафиксировать:
- ветку, из которой выполняется публикация;
- версию Node.js и пакетного менеджера;
- команду установки зависимостей;
- команду сборки;
- каталог результата;
- переменные окружения;
- домен и значение
base; - способ проверки результата после деплоя.
Публикация должна быть воспроизводимой: одинаковый исходный код и одинаковые настройки должны давать сопоставимый результат. Секреты нельзя помещать в публичный исходный код. Переменные, которые попадают в клиентскую сборку, не следует считать секретными, потому что они становятся доступными браузеру.
Контроль перед публикацией
Проверка React-сайта на Vite должна включать сборку, результат в dist, публикацию и поведение сайта после размещения. Минимальная последовательность выглядит так:
- Запустить установку зависимостей в чистом окружении.
- Выполнить производственную сборку.
- Проверить отсутствие ошибок сборки и предупреждений, влияющих на результат.
- Открыть сборку через локальный просмотр.
- Проверить главную и вложенные страницы.
- Проверить загрузку JavaScript, CSS, изображений и шрифтов.
- Сверить значение
baseс фактическим адресом размещения. - Проверить исходный HTML публичных страниц.
- Проверить title, description, H1, canonical и основной текст.
- Перезагрузить вложенный URL напрямую.
- Проверить неизвестный URL и статус ответа.
- Проверить мобильное отображение и формы.
- После публикации проверить серверные заголовки, кеширование и логи.
- Передать опубликованные URL в инструменты поисковых систем.
Сборка считается готовой не тогда, когда появился каталог dist, а тогда, когда опубликованный сайт выдаёт правильный документ по каждому важному адресу и сохраняет это поведение после обновления страницы.
Когда Vite не решает проблему
Vite ускоряет разработку и создаёт производственные ресурсы, но не исправляет архитектурные ошибки сайта. Он не выбирает стратегию рендеринга, не формирует содержательную структуру страниц, не настраивает серверные статусы и не определяет, какие URL должны индексироваться.
Если проекту нужны публичные страницы с отдельным HTML, нужно заранее выбрать статическую генерацию, предварительный рендеринг, SSR или другой серверный механизм. Если проект является закрытым приложением, клиентский рендеринг может быть достаточным, потому что SEO не является его основной задачей.
Проблема появляется, когда сайт публикуется как обычная статическая сборка, но от него ожидается поведение полноценного серверного приложения без настройки маршрутов и HTML. В этом случае нужно разделить требования к интерфейсу, публикации, поисковой доступности и серверной обработке.
Чек-лист
- Исходники проекта разделены на компоненты, маршруты, стили и ресурсы.
- Производственная сборка завершается без критических ошибок.
- Каталог
distсодержит ожидаемый результат. baseсоответствует адресу публикации.- JavaScript, CSS, изображения и шрифты загружаются по правильным путям.
- Стратегия рендеринга выбрана для каждого типа страницы.
- Публичные маршруты открываются напрямую.
- Вложенные URL не ломаются после перезагрузки.
- Неизвестные адреса не превращаются в главную страницу со статусом 200.
- Исходный HTML содержит основное содержание и метаданные.
- Title, description, H1 и canonical соответствуют маршруту.
- Первый клиентский рендер совпадает с предварительно созданным HTML.
vite previewне используется как производственный сервер.- После деплоя проверены статусы, заголовки, кеширование и логи.
Источники
- Vite. Building for Production: https://vite.dev/guide/build
- Vite. Deploying a Static Site: https://vite.dev/guide/static-deploy
- Vite. Command Line Interface: https://vite.dev/guide/cli
- Vite. Server-Side Rendering: https://vite.dev/guide/ssr
- React Router. Rendering Strategies: https://reactrouter.com/start/framework/rendering
- React Router. Deploying: https://reactrouter.com/start/framework/deploying


