От React-приложения к боевому Next.js: практическое руководство по первой миграции
Практическое пошаговое руководство по миграции с Create React App (CRA) на готовый к продакшену Next.js в 2025 году — почему стоит перейти, как спланировать миграцию и какие подводные камни учесть.
От React-приложения к боевому Next.js: практическое руководство по первой миграции
Если вы создавали своё приложение с помощью Create React App (CRA) несколько лет назад, вы далеко не одиноки — и вы точно не одни, если эта конфигурация начала ощущаться ограничивающей.
В 2025 году Next.js стал де-факто стандартом для продакшен‑приложений на React, особенно если вам важны:
- Производительность
- SEO и удобно шарящиеся страницы
- Масштабируемость и сопровождаемость
- Современные full‑stack‑возможности
Хорошая новость: миграция с CRA на Next.js — это уже хорошо проторенная, практическая дорожка. Многие команды уже прошли этот путь — иногда с крупными и сложными кодовыми базами — и общие паттерны хорошо понятны. В этом посте мы разберём вашу первую миграцию с CRA к боевому приложению на Next.js, делая упор на практические шаги, а не теорию.
Зачем мигрировать с CRA на Next.js в 2025 году?
Прежде чем переходить к «как», важно чётко понимать «зачем».
1. Next.js — это уже full‑stack‑платформа, а не «просто React‑фреймворк»
Next.js начинался как фреймворк для серверного рендеринга React. Сегодня это полноценная full‑stack‑платформа, которая даёт вам:
- Маршрутизацию на основе файловой системы (без ручной настройки react-router)
- Получение данных на сервере (SSR, SSG, ISR)
- API‑роуты, server actions и edge‑функции
- Встроенную оптимизацию изображений, шрифтов и аналитику
- Первоклассную поддержку TypeScript и современных бандлеров
Для многих команд это означает единую платформу вместо «склейки» CRA + Express + кастомный SSR + конфигурации Webpack.
2. Лучшая производительность и SEO «из коробки»
CRA собирает Single Page Application (SPA), где всё рендерится на клиенте после загрузки JavaScript. Это может ухудшать:
- First Contentful Paint и Core Web Vitals
- SEO, поскольку краулеры без JS могут почти ничего не увидеть в HTML
Next.js предоставляет:
- Server-Side Rendering (SSR) для динамического контента
- Static Site Generation (SSG) для быстрых, кешируемых страниц
- Incremental Static Regeneration (ISR) для гибридных сценариев
Во многих реальных миграциях сразу заметны улучшения скорости страниц, показателей Lighthouse и позиций в поиске.
3. Проверен на крупных проектах
Крупные open source и коммерческие приложения уже мигрировали с «ванильного» React на Next.js, показав:
- Реализуемость миграции даже для больших кодовых баз
- Сопровождаемость конвенций Next.js на длительном горизонте
- Возможность постепенного перехода на Next.js без тотального переписывания
Вы идёте не в неизвестность — вы следуете по пути, который уже прошли многие.
Стратегия миграции: не переписывать с нуля, а внедрять по шагам
Самый быстрый способ провалить миграцию — воспринимать её как полный рефакторинг «с нуля». Вместо этого думайте о ней как о пошаговом процессе.
Практичный подход:
- Создать новый проект на Next.js
- Отзеркалить структуру CRA в
appилиpages - Сначала перенести общий код (компоненты, хуки, утилиты)
- Постепенно переносить маршруты/страницы
- Вводить серверные возможности (SSR/SSG, API‑роуты), когда всё стабилизируется
- Подготовить приложение к продакшену (окружения, CI/CD, мониторинг)
Разберём по шагам.
Шаг 1: Настройте новый проект на Next.js
В корне репозитория (или в новом репо) выполните:
npx create-next-app@latest
Вам зададут несколько вопросов. Типичные продакшен‑настройки для 2025 года:
- TypeScript: Yes
- ESLint: Yes
- App Router (по умолчанию): Yes — это современная система роутинга Next.js
- Tailwind (опционально): Yes, если вы уже его используете или хотите utility‑CSS
В итоге вы получите полностью настроенное приложение на Next.js с адекватными настройками по умолчанию.
Совет: создайте проект в соседней папке (например,
my-app-next), чтобы во время миграции удобно ссылаться на существующий код CRA.
Шаг 2: Поймите ключевые отличия
Перед переносом файлов важно согласовать основные концептуальные изменения.
1. Маршрутизация
- CRA: обычно использует
react-routerс кастомной конфигурациейRoutes. - Next.js: роутинг основан на файловой структуре.
- В App Router маршруты живут в
app/<route>/page.tsx. - Вложенные папки соответствуют вложенным маршрутам.
- В App Router маршруты живут в
Пример:
app/ page.tsx -> / dashboard/ page.tsx -> /dashboard blog/ [slug]/ page.tsx -> /blog/:slug
2. Точка входа
- CRA:
src/index.tsxмонтирует<App />в корневой div. - Next.js: вы не вызываете
ReactDOM.renderвручную. Next делает это сам. Вы описываете страницы и layout’ы.
3. Получение данных
- CRA: всё получение данных происходит на клиенте (например, в
useEffect). - Next.js: вы можете получать данные на сервере (в
page.tsx,layout.tsxили server actions) или на клиенте.
Это серьёзный сдвиг и ключевая причина, почему улучшаются производительность и SEO.
Шаг 3: Сначала перенесите общий код
Начните с частей, которые не завязаны на роутинг или особенности получения данных.
Перенесите из src/ в CRA в app/ или верхнеуровневый src/ в Next.js:
- UI‑компоненты (кнопки, формы, модалки)
- Хуки (
useAuth,useThemeи т.п.) - Утилитарные функции (форматтеры, API‑клиенты)
- Стили (CSS‑модули, конфигурация Tailwind, глобальные стили)
Старайтесь сохранить пути импорта максимально похожими. Если вы использовали абсолютные импорты в CRA, настройте их в jsconfig.json или tsconfig.json в Next.js.
Пример tsconfig.json с alias‑путями:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@/components/*": ["./components/*"], "@/lib/*": ["./lib/*"] } } }
Шаг 4: Перенесите маршруты в страницы Next.js
Теперь можно мигрировать сами представления.
Отразите роуты CRA в структуре Next.js
Если ваш App.tsx в CRA выглядит так:
<Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/products/:id" element={<ProductDetail />} /> </Routes>
В App Router Next.js вы можете создать такую структуру:
app/ page.tsx -> Home about/ page.tsx -> About products/ [id]/ page.tsx -> ProductDetail
Скопируйте каждый компонент страницы из CRA в соответствующий page.tsx. При необходимости поправьте импорты.
Используйте layout’ы для общего UI
Если в CRA ваш App.tsx оборачивает все страницы в общий layout (navbar, footer и т.п.), перенесите эту логику в app/layout.tsx.
// app/layout.tsx import "./globals.css"; import { ReactNode } from "react"; export default function RootLayout({ children }: { children: ReactNode }) { return ( <html lang="en"> <body> <Header /> <main>{children}</main> <Footer /> </body> </html> ); }
Так вы уменьшите дублирование и централизуете все кросс‑страничные вещи.
Шаг 5: Постепенно внедряйте SSR и SSG
На первых этапах вы можете оставить клиентский фетчинг данных, чтобы минимизировать поведение, отличающееся от CRA. Для страниц или компонентов, использующих хуки вроде useState или useEffect, в App Router добавьте директиву "use client" в самом верху файла.
"use client"; export default function DashboardPage() { // client-side hooks and effects here }
После того как всё стабилизируется, начинайте переносить получение данных на сервер там, где это оправдано.
Пример: перевод «тяжёлой» по данным страницы на серверный рендеринг
Версия в CRA:
function BlogPost() { const { slug } = useParams(); const [post, setPost] = useState<Post | null>(null); useEffect(() => { fetch(`/api/posts/${slug}`) .then(res => res.json()) .then(setPost); }, [slug]); // render }
Server‑rendered‑страница в Next.js (App Router):
// app/blog/[slug]/page.tsx async function getPost(slug: string) { const res = await fetch(`${process.env.API_URL}/posts/${slug}`, { cache: "no-store", }); if (!res.ok) throw new Error("Failed to fetch post"); return res.json(); } export default async function BlogPostPage({ params, }: { params: { slug: string }; }) { const post = await getPost(params.slug); return ( <article> <h1>{post.title}</h1> <div dangerouslySetInnerHTML={{ __html: post.content }} /> </article> ); }
Теперь HTML статьи генерируется на сервере, что улучшает SEO и первоначальную скорость загрузки.
Шаг 6: Используйте Next.js для backend‑логики (API‑роуты и Server Actions)
Next.js — это не только рендеринг; это full‑stack‑платформа.
Если раньше у вас были:
- Отдельный сервер на Node/Express
- Или «самодельный» API прямо внутри проекта CRA
Во многих случаях можно перенести эндпоинты в API‑роуты Next.js или server actions.
Пример API‑роута:
// app/api/posts/[id]/route.ts import { NextResponse } from "next/server"; export async function GET(_: Request, { params }: { params: { id: string } }) { const post = await db.posts.find(params.id); return NextResponse.json(post); }
Так фронтенд‑ и бэкенд‑логика оказываются в одном, цельном кодовом базе.
Шаг 7: Подготовьте приложение к продакшену
Продакшен‑готовое приложение на Next.js — это больше, чем просто «всё работает локально».
Переменные окружения
Используйте .env.local, .env.production и т.п., обращайтесь к ним через process.env.MY_KEY. Настройте переменные в платформе деплоя (Vercel, AWS, Netlify и др.).
Сборка и деплой
- Настройте CI‑пайплайн (
npm run lint,npm run test,npm run build). - Убедитесь, что ваш хостинг поддерживает используемые фичи Next.js (SSR, edge‑функции и т.п.).
- Следите за размером бандла и производительностью (вывод
next build, Lighthouse).
Обозримость и наблюдаемость
- Добавьте логирование и отслеживание ошибок (Sentry, LogRocket и др.).
- Используйте встроенную аналитику Next или свои инструменты.
На этом этапе реальные миграции особенно окупаются: команды часто отмечают упрощение пайплайна деплоя и более предсказуемую производительность после перехода на Next.js.
Частые ловушки и как их избежать
- Смешивание клиентских и серверных концепций: в App Router чётко разделяйте серверные компоненты (по умолчанию) и клиентские (
"use client"). - Чрезмерное использование клиентских компонентов: помечайте компонент как клиентский только если ему нужны хуки, браузерные API или обработчики событий; всё остальное оставляйте серверным ради производительности.
- Игнорирование SEO и метаданных: используйте metadata API Next или аналоги
<Head>для настройки title, description и Open Graph‑данных для каждой страницы. - «Большой взрыв» (big-bang) переписывания: мигрируйте постепенно. Доставляйте маленькие части, проверяйте, затем двигайтесь дальше.
Итог: первая миграция — только начало
Переход с Create React App на Next.js больше не выглядит рискованным экспериментом; это проверенный путь модернизации, который выравнивает ваше приложение с тем, как в 2025 году принято создавать и развёртывать React‑проекты.
Если следовать структурированному, поэтапному подходу:
- Создать приложение на Next.js
- Перенести общие компоненты и утилиты
- Перевести роуты в файловые страницы
- Постепенно внедрять серверный рендеринг и статическую генерацию
- Консолидировать backend‑логику в API‑роутах и серверных фичах
- Подготовить инфраструктуру к реальному продакшен‑трафику
В итоге вы получите не просто «React‑приложение, которое работает», а боевую full‑stack‑платформу: быстрее, масштабируемее и гораздо лучше оптимизированную под SEO и современные ожидания пользователей.
Первая миграция научит вас основным паттернам. После неё Next.js станет не просто ещё одним инструментом, а дефолтным способом думать о создании веб‑приложений на React.