Next.js vs чистый React: что выбрать под проект и как объяснить выбор на интервью
Сравниваем Next.js и чистый React: архитектура, SSR и RSC, производительность, стоимость разработки, типичные ошибки и критерии выбора для production.
- Введение
- Что именно сравниваем
- Что такое чистый React в реальном проекте
- Что добавляет Next.js поверх React
- Архитектурный разбор: где проходит граница ответственности
- Контекст задачи
- Схема для чистого React
- Схема для Next.js
- Где ломается принятие решений
- Код: типичный экран на чистом React
- Код: тот же сценарий на Next.js App Router
- Код: мутации и формы как точка расхождения
- Сравнительная таблица: когда что выбирать
- Разбор производительности: где система реально платит
- Что дорого в чистом React
- Что дорого в Next.js
- Когда оптимизация оправдана
- Production pitfalls: где команды чаще всего ошибаются
- 1. Берут Next.js для чистой SPA-задачи
- 2. Пытаются лечить публичный продукт одной CSR-моделью
- 3. Ставят "use client" слишком высоко
- 4. Недооценивают цену инфраструктуры
- Практики, которые обычно работают лучше
- Архитектурные практики
- Практики кода
- Наблюдаемость
- Rollout и откат
- Частые ошибки
- Как отвечать на интервью
- FAQ
- Правда ли, что Next.js нужен только для SEO?
- Если проект на Next.js, можно ли писать обычные клиентские компоненты?
- Когда чистый React объективно проще?
- Можно ли начать с чистого React, а потом перейти на Next.js?
- Какой главный неверный вывод по теме Next.js vs React?
- Итоги
Введение
Запрос Next.js vs чистый React почти всегда возникает не из теории, а из вполне реального спора в команде. Один разработчик хочет взять Next.js, потому что там уже есть маршрутизация, SSR, App Router и server-first модель. Другой говорит, что для продукта после логина это лишняя платформа, и обычный React с Vite даст меньше ограничений и дешевле в поддержке. Если нужен контекст по самой клиентской базе, с ним можно ознакомится в статье про React и Vite как современный старт проекта.
Самая частая ошибка в этом обсуждении такая: Next.js и React начинают сравнивать так, будто это продукты одного уровня. Но React это библиотека для построения UI, а Next.js это фреймворк поверх React со своими соглашениями о роутинге, рендеринге, серверных границах, сборке и доставке приложения. Поэтому корректный вопрос звучит не "что лучше", а "нужна ли проекту именно эта платформа поверх React".
С практической точки зрения выбор обычно зависит от пяти факторов: где рендерится первый экран, нужен ли SEO-трафик, сколько логики хочется держать на сервере, насколько команда готова следовать соглашениям фреймворка и кто будет платить за сложность инфраструктуры. Ниже разберем это не по маркетинговым обещаниям, а по архитектуре, стоимости и production-рискам.
Больше вопросов в Telegram
Ежедневные разборы и реальные кейсы с интервью.
Что именно сравниваем
Что такое чистый React в реальном проекте
Под чистым React почти никогда не имеют в виду приложение вообще без инструментов. Обычно это такой стек:
Reactкак слой UI;Viteили другой сборщик;React Routerдля маршрутов;- отдельный backend или BFF;
- клиентский
fetch, TanStack Query или другой слой загрузки данных; - собственные решения для развёртывания, кеширования и SSR, если он вообще нужен.
То есть "чистый React" в разговоре команды обычно означает: мы сами собираем платформу из частей и берем только те слои, которые реально нужны проекту.
Что добавляет Next.js поверх React
Next.js предоставляет готовое решение вместо такого конструктора. Он дает:
- файловую маршрутизацию;
- серверный рендеринг и статическую генерацию;
- App Router и server-first модель;
- React Server Components;
- Server Actions и серверные мутации;
- встроенную работу со сборкой, чанками и delivery pipeline;
- единый deployment-контур для фронтенда и серверных частей.
Отсюда и основной компромисс. В чистом React больше свободы и меньше платформенных ограничений. В Next.js меньше решений нужно принимать вручную, но выше цена жизни внутри фреймворка.
Архитектурный разбор: где проходит граница ответственности
Контекст задачи
Представим два продукта:
- Публичный каталог вакансий или контентная витрина, где важны индексация, быстрый первый экран и работа с серверными данными.
- Внутренняя CRM после авторизации, где основная ценность начинается после входа, а почти весь экран живет на клиентской интерактивности.
В этих двух системах одинаковый стек будет давать разный эффект. Именно поэтому вопрос выбора нельзя решать только предпочтениями команды.
Схема для чистого React
Упрощенный поток в React SPA обычно такой:
- Сервер отдает HTML-shell и клиентский bundle.
- Браузер загружает JavaScript.
- React монтирует приложение.
- Роутер определяет экран.
- Компоненты или query-слой делают запросы к API.
- Пользователь получает данные после клиентского fetch.
Такая схема хорошо подходит там, где SEO не критичен, а интерфейс и так требует много клиентского состояния. Проблема начинается, когда ту же модель без изменений переносят на публичные страницы. Тогда первый экран, индексация и latency до полезного контента начинают зависеть от того, насколько быстро браузер скачает и выполнит JS.
Схема для Next.js
В Next.js, особенно в App Router, поток уже другой:
- Запрос приходит на сервер.
- Серверный слой получает данные рядом с backend.
- Сервер рендерит HTML и RSC payload.
- Пользователь видит содержимое раньше.
- Клиент подключает только интерактивные острова.
- Мутации и чтение данных могут оставаться ближе к серверу.
Это уже не просто SSR как флаг в конфиге. Это другой подход к границе между клиентом и сервером. Он пересекается с темами SSR vs CSR vs RSC и Server Components в React, потому что Next.js не только меняет способ отдачи HTML, но и меняет стоимость клиентского JavaScript.
Где ломается принятие решений
Ошибочный подход выглядит так:
- брать Next.js только потому, что "так современнее";
- брать чистый React только потому, что "так проще";
- не разделять публичные страницы и закрытые интерфейсы;
- обсуждать фреймворк без учета deployment, кеша и команды backend.
Правильный архитектурный вопрос звучит иначе: где проект реально выигрывает от server-first модели, а где она просто усложняет архитектуру.
Код: типичный экран на чистом React
Ниже упрощенный вариант каталога на React + React Router, где данные загружаются после монтирования экрана:
import { useEffect, useState } from "react";
type Product = {
id: string;
title: string;
price: number;
};
export default function CatalogPage() {
const [items, setItems] = useState<Product[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
let cancelled = false;
fetch("/api/catalog")
.then((res) => {
if (!res.ok) {
throw new Error("Request failed");
}
return res.json();
})
.then((data: Product[]) => {
if (!cancelled) {
setItems(data);
setLoading(false);
}
})
.catch(() => {
if (!cancelled) {
setError("Не удалось загрузить каталог");
setLoading(false);
}
});
return () => {
cancelled = true;
};
}, []);
if (loading) return <p>Загружаем каталог...</p>;
if (error) return <p>{error}</p>;
return (
<ul>
{items.map((item) => (
<li key={item.id}>
{item.title} - {item.price} ₽
</li>
))}
</ul>
);
}
Этот вариант неплох сам по себе. Для внутренней панели он может быть вполне приемлемым. Но на публичной странице у него есть понятная цена:
- первый полезный контент зависит от клиентского JS;
- есть фаза пустого экрана или skeleton;
- SEO и предпросмотр становятся слабее;
- данные и UI сильнее зависят от состояния браузера.
Если задача команды именно в том, чтобы быстро и предсказуемо разработать SPA, такой путь может быть рациональнее, чем полноценная server-first платформа.
Код: тот же сценарий на Next.js App Router
Теперь тот же каталог в server-first модели:
// app/catalog/page.tsx
type Product = {
id: string;
title: string;
price: number;
};
async function getCatalog(): Promise<Product[]> {
const res = await fetch("https://api.example.com/catalog", {
next: { revalidate: 60 },
});
if (!res.ok) {
throw new Error("Failed to load catalog");
}
return res.json();
}
export default async function CatalogPage() {
const items = await getCatalog();
return (
<ul>
{items.map((item) => (
<li key={item.id}>
{item.title} - {item.price} ₽
</li>
))}
</ul>
);
}
Здесь главное отличие не в синтаксисе, а в том, где живет работа:
- данные запрашиваются на сервере;
- HTML приходит уже с содержимым;
- клиент не обязан заново собирать весь экран;
- кэширование и revalidation становятся частью платформы.
Но и этот вариант не бесплатен. Теперь цена смещается на серверную инфраструктуру, дисциплину кеширования и корректную работу с server/client границами. Если почти весь экран интерактивный и зависит от локального состояния, выигрыш может быть заметно меньше, чем кажется на старте.
Код: мутации и формы как точка расхождения
Одно из самых заметных отличий проявляется не на чтении данных, а на записи. В чистом React форма часто выглядит так:
import { FormEvent, useState } from "react";
export function ProfileForm() {
const [pending, setPending] = useState(false);
const [message, setMessage] = useState("");
async function onSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
setPending(true);
const formData = new FormData(event.currentTarget);
const res = await fetch("/api/profile", {
method: "POST",
body: JSON.stringify({
displayName: String(formData.get("displayName") ?? ""),
}),
headers: {
"Content-Type": "application/json",
},
});
setPending(false);
setMessage(res.ok ? "Профиль обновлен" : "Ошибка обновления");
}
return (
<form onSubmit={onSubmit}>
<input name="displayName" />
<button disabled={pending} type="submit">
{pending ? "Сохраняем..." : "Сохранить"}
</button>
{message ? <p>{message}</p> : null}
</form>
);
}
В Next.js похожий сценарий можно реализовать через server-first слой и не переносить столько транспортной обвязки в клиент. Это одна из причин, почему тема напрямую пересекается со статьей про Server Actions в React.
Сравнительная таблица: когда что выбирать
| Критерий | Чистый React | Next.js | Когда выбор обычно оправдан |
|---|---|---|---|
| SEO и публичный трафик | Требует отдельного SSR/SSG решения или смирения с CSR | Сильный путь из коробки | Next.js для контентных и публичных страниц |
| Скорость старта команды | Быстрый вход в SPA без лишней платформы | Быстрый старт, если нужны соглашения фреймворка | React для простых SPA, Next.js для full-stack фронтенда |
| Стоимость клиентского JS | Зависит от архитектуры и легко разрастается | Ниже при узких server/client границах | Next.js, если важен server-first подход |
| Свобода архитектуры | Больше свободы, меньше правил | Больше соглашений, меньше ручной сборки | React, если нужны кастомные решения |
| Работа с серверными данными | Все нужно собирать вручную | Встроенная server-first модель | Next.js для data-heavy экранов |
| Deployment и инфраструктура | Проще для статического SPA | Сложнее, если нужен серверный рантайм | React для простого хостинга, Next.js для платформенного SSR |
| Внутренние панели после логина | Часто достаточно и даже проще | Может быть избыточным | Чистый React |
| Глубина экосистемы React | Полная свобода выбора библиотек | Нужно учитывать совместимость с App Router и RSC | React, если проект сильно завязан на клиентские библиотеки |
Из таблицы полезно вынести один вывод: Next.js не заменяет React, а решает набор инфраструктурных задач вокруг него. Если этих задач у проекта нет, фреймворк не становится автоматически лучшим выбором.
Больше вопросов в Telegram
Ежедневные разборы и реальные кейсы с интервью.
Разбор производительности: где система реально платит
Что дорого в чистом React
У чистого React узкое место часто связано с браузером:
- большой стартовый bundle;
- клиентский fetch после mount;
- повторные рендеры при загрузке данных;
- задержка до первого полезного контента;
- дублирование логики агрегации данных на клиенте.
На ноутбуке разработчика это может выглядеть терпимо. На слабом устройстве или медленной сети становится видно, насколько дорого приложение запускается до того, как пользователь вообще начинает взаимодействовать с экраном.
Что дорого в Next.js
У Next.js основные издержки переносятся на серверную сторону:
TTFBзависит от задержки до источников данных;- серверный рендер нагружает инфраструктуру;
- ошибка в кэшировании быстро бьет по p95;
- широкая клиентская граница уничтожает выгоду RSC;
- гидрация все равно остается, если экран интерактивный.
Именно поэтому фраза "Next.js быстрее" без контекста слабая. Он может дать более ранний HTML и более узкий клиентский bundle, но при плохой архитектуре легко превратится в дорогой серверный слой плюс тяжелый клиент.
Когда оптимизация оправдана
Next.js чаще окупается, когда:
- есть публичные маршруты;
- важна индексация;
- экран в основном на чтение, а не полностью интерактивный;
- данные выгодно получать на сервере;
- команда готова держать дисциплину вокруг кэша и клиентских границ.
Чистый React чаще оправдан, когда:
- приложение живет внутри авторизации;
- пользователь все равно ждет инициализации сессии и API;
- большая часть экрана это клиентская интерактивность;
- нужен простой deployment без серверного рантайма;
- фреймворковые ограничения мешают больше, чем помогают.
Если в проекте болит не рендеринг, а размер графа зависимостей и сборка, полезно смотреть еще и на Webpack vs Vite для React, потому что часть проблем вообще не про Next.js, а про дисциплину вокруг бандла.
Прокачай React за 7 дней
20 вопросов и разборов по React Hooks.
Production pitfalls: где команды чаще всего ошибаются
1. Берут Next.js для чистой SPA-задачи
Симптомы:
- почти все экраны закрыты авторизацией;
- SEO не нужен;
- большая часть состояния и так живет в браузере;
- серверные возможности фреймворка используются точечно или вообще не используются.
Последствие: команда получает излишнюю платформенную сложность без заметной пользы.
Как выявить заранее: честно разделить маршруты на публичные и закрытые, а не ориентироваться на общий ажиотаж вокруг server-first.
2. Пытаются лечить публичный продукт одной CSR-моделью
Симптомы:
- raw HTML почти пустой;
- первый экран зависит от клиентского fetch;
- маркетинг жалуется на слабую индексацию и долгую загрузку витрин.
Последствие: бизнес-потребность в SEO и быстром первом контенте остается незакрытой.
Как выявить заранее: смотреть не только на удобство разработки на локальной машине, но и на то, что реально приходит в первом ответе сервера.
3. Ставят "use client" слишком высоко
Симптомы:
- после перехода на App Router bundle почти не уменьшается;
- server components есть только формально;
- layout и верхние route-сегменты стали клиентскими без жесткой причины.
Последствие: проект платит и за сложность Next.js, и за старую цену клиентского дерева.
Как поймать заранее: ревьюить клиентские границы как архитектурное решение, а не как случайную деталь файла.
4. Недооценивают цену инфраструктуры
Симптомы:
- команда думает только про developer experience;
- кеш, observability и rollback обсуждают уже после запуска;
- нет ясности, где будет жить серверный рантайм и как он масштабируется.
Последствие: технически красивое решение начинает дорого обходиться в эксплуатации.
Как поймать заранее: считать не только скорость локальной разработки, но и стоимость продакшн-контура.
Практики, которые обычно работают лучше
Архитектурные практики
- Выбирать стек по профилю маршрутов: публичные, закрытые, mixed.
- Проектировать экран сначала по данным и интерактивности, а потом подбирать платформу.
- Не сравнивать Next.js с React как взаимоисключающие сущности: React будет в обоих вариантах.
Практики кода
- В Next.js держать server/client границы узкими и объяснимыми.
- В чистом React не дублировать хаотично
fetchпо компонентам, а собирать ясный data layer. - Не переводить весь проект на универсальную абстракцию до появления реальной сложности.
Наблюдаемость
- Для React SPA смотреть на размер бандла, LCP, INP и реальную загрузку после монтирования.
- Для Next.js отдельно смотреть на
TTFB, cache hit rate, время рендера и стоимость гидрации. - Проверять raw HTML, а не только финальный DOM после полной загрузки.
Rollout и откат
- Не мигрировать все маршруты на Next.js или обратно одним шагом без профиля метрик.
- Начинать с маршрутов, где выгода понятна: каталог, статья, профиль, read-heavy экраны.
- Держать feature flag, то есть флаг включения, или хотя бы понятный путь отката для спорных решений.
Частые ошибки
- Говорить, что
Next.js = React. Это неточно: Next.js построен на React, но добавляет платформенные соглашения. - Считать, что чистый React всегда "устаревший". Для многих SPA это экономически лучший выбор.
- Считать, что Next.js автоматически решает производительность. Он лишь меняет, где вы за нее платите.
- Игнорировать разницу между публичными и закрытыми маршрутами.
- Выбирать стек по резюме или тренду, а не по архитектурному профилю продукта.
Как отвечать на интервью
Сильный ответ по теме Next.js vs чистый React обычно выглядит так:
- Сначала уточнить уровень сравнения: React это UI-библиотека, Next.js это фреймворк поверх React.
- Затем назвать критерий выбора: SEO, SSR, server-first архитектура, deployment, интерактивность, цена инфраструктуры.
- Потом показать границы:
Next.jsлучше там, где нужны публичные маршруты, ранний HTML, RSC и единые соглашения.Чистый Reactлучше там, где продукт в основном клиентский, живет после логина и не требует сложного серверного рендеринга. - Закончить компромиссом: выбор зависит не от моды, а от профиля маршрутов и стоимости поддержки.
Примерная формулировка может звучать так:
Если мне нужен публичный продукт с SEO, серверным рендерингом и возможностью держать слой чтения данных на сервере, я бы чаще смотрел в сторону Next.js. Если это внутренняя SPA после авторизации, где основная сложность в клиентской интерактивности, а серверный HTML почти ничего не дает, я бы выбрал React с более легким стеком вроде Vite и собрал только нужные слои.
Хороший признак зрелого ответа: вы не продаете один вариант как универсальный, а показываете, за что именно платит система в каждом случае.
Потренируйте React и Next.js вопросы на реальных интервью
Практика по React, Next.js, SSR, архитектуре экранов и performance помогает быстрее научиться объяснять не только инструменты, но и границы их применения.
FAQ
Правда ли, что Next.js нужен только для SEO?
Нет. SEO это лишь один из поводов. Next.js полезен еще и тогда, когда нужна server-first модель, работа с RSC, более узкий клиентский слой и единые соглашения по маршрутам, загрузке данных и рендерингу.
Если проект на Next.js, можно ли писать обычные клиентские компоненты?
Да. Next.js не отменяет клиентский React. Он просто позволяет держать часть дерева и данных на сервере, а интерактивные участки оставлять клиентскими.
Когда чистый React объективно проще?
Когда продукт по сути является SPA: личный кабинет, CRM, внутренняя панель, редактор, визуальный инструмент после логина. В таких сценариях стоимость Next.js может не окупиться.
Можно ли начать с чистого React, а потом перейти на Next.js?
Можно, но это не всегда легкая миграция. Чем больше в проекте ручных решений вокруг роутинга, data fetching и архитектуры экранов, тем дороже переход. Поэтому лучше принимать решение на основе профиля маршрутов заранее.
Какой главный неверный вывод по теме Next.js vs React?
Пытаться выбрать победителя "вообще". В реальной инженерной среде выбирают не победителя, а платформу под конкретный тип продукта, профиль трафика и ограничения команды.
Итоги
Next.js vs чистый React это не битва двух библиотек, а выбор между двумя уровнями платформы. В одном случае вы собираете стек сами и оставляете себе больше свободы. В другом берете готовую server-first систему с ее сильными сторонами и ограничениями.
Если проект живет на публичных маршрутах, зависит от SEO, выигрывает от серверного чтения данных и нуждается в более узком клиентском JavaScript, Next.js обычно оказывается сильным решением. Если же продукт почти целиком клиентский, работает после авторизации и не получает реальной пользы от SSR или RSC, чистый React часто оказывается проще, дешевле и более адекватным решением.
Лучшее решение здесь почти всегда не идеологическое, а инженерное: сначала понять профиль экранов и узкие места, потом выбирать платформу.
Больше вопросов в Telegram
Ежедневные разборы и реальные кейсы с интервью.
Автор
Lexicon Team
Читайте также
frontend
Когда нужен Next.js: признаки, что фреймворк окупится в проекте
Разбираем, когда нужен Next.js на практике: SEO, SSR, RSC, серверные мутации, стоимость инфраструктуры, типичные ошибки выбора и сильный ответ на интервью.
frontend
Hydration в React: что происходит после SSR и где ломается интерактивность
Разбираем hydration в React после SSR: как браузер связывает HTML с деревом React, почему возникают hydration mismatch, сколько стоит гидрация и как уменьшить клиентскую нагрузку.
frontend
React hydration errors: причины и решения без магии
Практический разбор React hydration errors: почему возникают ошибки гидрации после SSR, как их дебажить, чем опасны mismatch и какие решения реально работают в production.