Создание приложения React с нуля
Если ваше приложение имеет ограничения, с которыми плохо справляются существующие фреймворки, вы предпочитаете создать собственный фреймворк или просто хотите изучить основы React-приложений, вы можете собрать приложение React с нуля.
Deep Dive
Начать с нуля — это простой способ познакомиться с React, но важно понимать, что такой подход зачастую сводится к созданию собственного, спонтанно сформированного фреймворка. По мере роста требований вам, скорее всего, придётся решать задачи, характерные для фреймворков, для которых в рекомендованных нами решениях уже есть хорошо проработанные и поддерживаемые решения.
Например, если в будущем вашему приложению потребуется поддержка серверного рендеринга (SSR), статической генерации (SSG) или React Server Components (RSC), вам придётся реализовать это самостоятельно. То же самое касается будущих возможностей React, которые требуют глубокой интеграции на уровне фреймворка и которые вам придётся реализовывать самостоятельно, если вы захотите их использовать.
Рекомендованные нами фреймворки также помогают создавать более производительные приложения. Например, сокращение или устранение каскадов сетевых запросов улучшает пользовательский опыт. Это может быть не так важно на этапе создания небольшого проекта, но с ростом числа пользователей производительность может стать приоритетом.
Кроме того, такой путь усложняет получение поддержки: ваша реализация маршрутизации, получения данных и других функций будет уникальной. Выбирайте этот путь только в том случае, если готовы самостоятельно решать все возникающие задачи или уверены, что вам никогда не понадобится соответствующий функционал.
Для списка рекомендуемых фреймворков смотрите Создание React-приложения.
Шаг 1: Установка инструмента сборки
Первым шагом будет установка инструмента сборки, например, vite
, parcel
, или rsbuild
. Эти инструменты позволяют упаковывать и запускать исходный код, предоставляют локальный сервер разработки и команду сборки для деплоя приложения на продакшн-сервер.
Vite
Vite — это инструмент сборки, нацеленный на быструю и лёгкую разработку современных веб-приложений.
Vite следует определённой философии и поставляется с продуманными настройками по умолчанию. У него также есть богатая экосистема плагинов, поддерживающих fast refresh, JSX, Babel/SWC и других функций. Ознакомьтесь с React-плагином для Vite или React SWC-плагином, а также примером проекта SSR на Vite, чтобы начать работу.
Vite уже используется как инструмент сборки в одном из рекомендованных нами фреймворков: React Router.
Parcel
Parcel совмещает удобство начальной настройки с масштабируемой архитектурой, которая позволяет развивать проект от простого прототипа до крупного продакшн-приложения.
Parcel поддерживает встроенную поддержку fast refresh, JSX, TypeScript, Flow и стилизацию. Ознакомьтесь с Parcel’s React рецептом, чтобы начать.
Rsbuild
Rsbuild — это инструмент сборки на базе Rspack, который предлагает безупречную систему для разработки React-приложений. Он включает в себя оптимизированные настройки и улучшения производительности.
Rsbuild поддерживает встроенную поддержку fast refresh, JSX, TypeScript и стилизацию. Ознакомьтесь с Rsbuild’s React руководство, чтобы начать.
Шаг 2: Реализация распространённых паттернов приложения
Инструменты сборки, упомянутые выше, позволяют начать с клиентского одностраничного приложения (SPA), но не предоставляют решения для таких задач, как маршрутизация, получение данных или стилизация.
Экосистема React предлагает множество решений для этих задач. Ниже приведены наиболее популярные из них — вы можете выбрать их или использовать альтернативы, если они вам ближе.
Маршрутизация
Маршрутизация определяет, какой контент или страницу показывать пользователю при переходе по определённому URL. Необходимо настроить маршрутизатор, чтобы сопоставлять URL-адреса с разными частями приложения. Также нужно обрабатывать вложенные маршруты, параметры маршрута и параметры запроса. Маршруты можно описывать в коде или определять по структуре файлов и папок.
Современные маршрутизаторы обычно включают поддержку получения данных (в том числе префетчинга для ускоренной загрузки страниц), разделения кода (для уменьшения размера клиентского бандла) и способов рендеринга страниц (чтобы определить, как будет формироваться каждая страница).
Рекомендуем использовать:
Получение данных
Получение данных с сервера или другого источника — ключевая часть большинства приложений. Чтобы всё работало правильно, нужно учитывать состояние загрузки, ошибки и кэширование данных — всё это может быть сложно реализовать вручную.
Специализированные библиотеки для получения данных берут эти задачи на себя. Они позволяют сосредоточиться на том, какие данные нужны приложению и как их отображать.Такие библиотеки можно использовать прямо внутри компонентов, а также интегрировать в загрузчики маршрутов для ускоренного префетчинга и повышения производительности, включая использование при серверном рендеринге.
Важно: если загружать данные прямо в компонентах, это может привести к каскадной задержке (waterfall). Лучше делать префетчинг в загрузчиках маршрутов или на сервере — это позволит загрузить все данные до или во время рендера страницы.
Если вы получаете данные с большинства бэкендов или REST‑API, мы рекомендуем использовать:
Если вы работаете с GraphQL‑API, мы рекомендуем использовать:
Разделение кода
Разделение кода — это процесс разбиения приложения на более мелкие бандлеры, которые подгружаются по мере необходимости. По мере добавления новых функций и зависимостей размер клиентского кода увеличивается. Это может привести к тому, что приложение начнёт загружаться медленно, поскольку весь код нужно будет передать в браузер до начала работы. Снизить задержки помогают такие подходы, как кэширование, отказ от неиспользуемых функций и зависимостей, а также перенос части кода на сервер. Однако эти методы не являются полноценным решением и при чрезмерном использовании могут начать ограничивать функциональность приложения.
Если вы полагаетесь на то, что само приложение будет делить код, вы можете столкнуться с ситуацией, когда загрузка становится даже медленнее, чем без разделения. Например, lazily loading — если вы отложенно подгружаете компонент диаграммы, сначала загружается сам код диаграммы (отдельно от остального кода приложения), а затем — данные для её отображения. Parcel поддерживает разделение кода с помощью React.lazy. Однако если данные для диаграммы загружаются уже после того, как она была отрендерена, пользователю придётся ждать дважды. Это и называется эффектом “waterfall”: вместо одновременной загрузки данных и кода, вы ждёте выполнения одного шага за другим.
Разделение кода по маршрутам — особенно в сочетании с бандлингом и загрузкой данных — может существенно сократить начальное время загрузки приложения и ускорить отображение основного контента — (Largest Contentful Paint).
Для инструкций по разделению кода смотрите документацию:
Повышение производительности приложения
Так как выбранные вами инструменты сборки по умолчанию поддерживают только одностраничные приложения (SPA), для повышения производительности может потребоваться реализовать другие подходы к рендерингу, такие как серверный рендеринг (SSR), статическая генерация сайта (SSG) и/или React Server Components (RSC). Даже если на начальном этапе такие возможности вам не нужны, в будущем может появиться необходимость использовать SSR, SSG или RSC для отдельных маршрутов приложения.
-
Одностраничные приложения (SPA) — загружают один HTML-файл и динамически обновляют содержимое по мере взаимодействия пользователя с приложением. Такой подход упрощает старт разработки, но может приводить к более медленной первоначальной загрузке. Для большинства инструментов сборки архитектура SPA является вариантом по умолчанию.
-
Серверный рендеринг (SSR) с потоковой передачей — выполняет рендеринг страницы на сервере и отправляет клиенту уже готовый HTML. Это может существенно улучшить производительность, но требует более сложной настройки и сопровождения по сравнению с SPA. А добавление потоковой передачи (streaming) делает SSR ещё более сложным в реализации. Смотрите: руководство по SSR для Vite.
-
Статическая генерация сайта (SSG) — создаёт статические HTML-файлы для вашего приложения во время сборки. Это улучшает производительность, но настройка и поддержка могут оказаться даже сложнее, чем при использовании SSR. Смотрите: руководство по SSG для Vite.
-
React Server Components (RSC) — RSC позволяют объединять компоненты, рендерящиеся во время сборки, только на сервере и интерактивные компоненты в одном дереве React. Это может серьёзно повысить производительность приложения, но на текущем этапе требует глубокой технической подготовки и опыта для настройки и сопровождения. Смотрите: примеры RSC для Parcel.
Ваша стратегия рендеринга должна быть интегрирована с маршрутизатором, чтобы приложения, построенные на вашем фреймворке, могли выбирать подходящий способ рендеринга для каждого маршрута. Это позволит применять разные стратегии без необходимости переписывать всё приложение. Например, главная страница может быть сгенерирована статически (SSG), а лента новостей — рендериться на сервере (SSR) для большей динамичности.
Правильно подобранная стратегия рендеринга для каждого маршрута помогает сократить: (Time to First Byte)— время до получения первого байта контента, (First Contentful Paint)— время до отображения первого видимого контента, (Largest Contentful Paint) — время до отображения основного содержимого страницы.
И многое другое…
Это лишь часть аспектов, которые стоит учитывать при создании приложения с нуля. Часто задачи тесно связаны друг с другом, и решение одной может потребовать глубокого понимания остальных.
Если вы не хотите решать всё самостоятельно, начните с фреймворка, в который всё это уже встроено.