1. Що таке Next.js і які його основні можливості?
Next.js — це React-фреймворк для продакшену, який розширює можливості React та вирішує типові проблеми SPA, такі як SEO, продуктивність, маршрутизація та робота з сервером.
Починаючи з Next.js 13+, основним підходом є App Router, який у Next.js 16+ є стандартом для розробки.
Основні можливості Next.js:
- Гібридний рендеринг
Next.js підтримує кілька стратегій рендерингу в межах одного застосунку:
- Server Components (default) — виконуються на сервері
- Server-Side Rendering (SSR)
- Static Site Generation (SSG)
- Incremental Static Regeneration (ISR)
Це дозволяє оптимально балансувати між продуктивністю та динамічністю.
- App Router та файлова маршрутизація
Маршрути створюються на основі структури папок у app/:
app/
├─ page.tsx // /
├─ blog/
│ └─ page.tsx // /blog
└─ layout.tsx // спільний layoutПідтримуються:
- вкладені layouts
- loading / error states
- route segments
- middleware
- React Server Components
За замовчуванням компоненти є серверними, що дозволяє:
- зменшити розмір JS-бандла
- безпечно працювати з БД та секретами
- виконувати data fetching без useEffect
export default async function Page() {
const data = await fetch('https://api.example.com/data').then(res => res.json());
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}- Вбудований data fetching
Next.js інтегрує fetch з контролем кешування та revalidation:
await fetch(url, { cache: 'no-store' }); // SSR
await fetch(url, { next: { revalidate: 60 } }); // ISR- Оптимізації з коробки
Next.js надає вбудовані оптимізації:
- автоматичний code splitting
- оптимізація зображень (next/image)
- оптимізація шрифтів (next/font)
- streaming та partial rendering
- Fullstack можливості
Next.js дозволяє будувати fullstack-застосунки:
- Route Handlers (app/api)
- Server Actions
- Middleware
- інтеграція з базами даних та auth
Коротко:
- Next.js — це production-ready React-фреймворк
- App Router та Server Components — основа сучасного Next.js
- Забезпечує високу продуктивність, SEO та масштабованість
2. Чим Next.js відрізняється від Create React App?
Create React App (CRA) — це інструмент для швидкого створення клієнтського React-застосунку (SPA), тоді як Next.js — повноцінний React-фреймворк, орієнтований на продакшен і fullstack-розробку.
Ключові відмінності:
- Рендеринг
-
CRA:
- лише Client-Side Rendering (CSR)
- HTML генерується в браузері
- гірший SEO та повільніший first paint
-
Next.js:
- Server Components (default)
- SSR / SSG / ISR
- streaming та partial rendering
- кращий SEO та продуктивність
- Архітектура
-
CRA:
- тільки frontend
- відсутній серверний шар
- API та auth — зовнішні сервіси
-
Next.js:
- fullstack-фреймворк
- Route Handlers, Server Actions, Middleware
- безпечна робота з БД та секретами
- Маршрутизація
-
CRA:
- ручне налаштування (
react-router) - вся логіка на клієнті
- ручне налаштування (
-
Next.js:
- файлова маршрутизація (
app/) - layouts, loading/error states
- nested routing без додаткових бібліотек
- файлова маршрутизація (
- Продуктивність та оптимізації
-
CRA:
- мінімальні оптимізації
- налаштовуються вручну
-
Next.js:
- автоматичний code splitting
- оптимізація зображень та шрифтів
- менший JS-бандл завдяки Server Components
- Статус проєкту
-
CRA:
- проєкт deprecated
- не рекомендований для нових застосунків
-
Next.js:
- активно розвивається
- стандарт де-факто для React у продакшені
- Використання в реальних проєктах
-
CRA підходить для:
- навчальних або простих SPA
- прототипів
-
Next.js підходить для:
- SEO-орієнтованих застосунків
- складних UI з серверною логікою
- масштабованих продуктів
Коротко:
- CRA — це клієнтський SPA-бутстрап, Next.js — fullstack-фреймворк
- Next.js підтримує серверний рендеринг та оптимізації з коробки
- Для нових продакшен-проєктів обирають Next.js
3. Яку команду використовують для створення нового застосунку Next.js?
Для створення нового застосунку на Next.js+ використовується офіційний
CLI-інструмент create-next-app.
Найпоширеніша та рекомендована команда:
npx create-next-app@latestПісля запуску CLI запропонує інтерактивну конфігурацію, зокрема:
- використання TypeScript
- App Router (
app/) — рекомендовано - ESLint
- Tailwind CSS
- alias для імпортів (
@/) - використання
src/директорії
Приклад створення проєкту з іменем:
npx create-next-app@latest my-next-appЩо створюється за замовчуванням (Next.js 16+)
- структура з App Router
app/layout.tsx— кореневий layoutapp/page.tsx— головна сторінка- підтримка React Server Components
- готова продакшен-конфігурація
my-next-app/
├─ app/
│ ├─ layout.tsx
│ └─ page.tsx
├─ public/
├─ next.config.js
└─ package.jsonВажливе зауваження
- Create React App не використовується
- Pages Router не є стандартом для нових проєктів
- create-next-app одразу створює production-ready середовище
Коротко:
- Для створення Next.js застосунку використовують npx create-next-app@latest
- CLI автоматично налаштовує App Router і сучасний стек
- Це рекомендований і єдиний актуальний спосіб старту з Next.js 16+
4. Яка різниця між Next.js та звичайним React-застосунком?
Звичайний React-застосунок (SPA) — це клієнтський UI-рівень, тоді як Next.js — це повноцінний React-фреймворк, який вирішує типові продакшен-проблеми на рівні архітектури.
- Рендеринг
-
React SPA:
- лише Client-Side Rendering (CSR)
- HTML формується в браузері
- залежність від
useEffectдля data fetching
-
Next.js:
- React Server Components (default)
- підтримка SSR / SSG / ISR
- data fetching на сервері без
useEffect - кращий SEO та швидший first load
- Архітектурний підхід
-
React SPA:
- лише frontend
- бекенд — окремий сервіс
- немає серверної логіки в проєкті
-
Next.js:
- fullstack-фреймворк
- Server Actions, Route Handlers, Middleware
- безпечна робота з БД, токенами, секретами
- Маршрутизація
-
React SPA:
- потребує сторонніх бібліотек (
react-router) - маршрути описуються вручну
- потребує сторонніх бібліотек (
-
Next.js:
- файлова маршрутизація через
app/ - layouts, nested routes, loading/error стани
- менше boilerplate-коду
- файлова маршрутизація через
- Продуктивність
-
React SPA:
- великий JS-бандл
- рендеринг повністю на клієнті
-
Next.js:
- автоматичний code splitting
- менший JS-бандл завдяки Server Components
- streaming та partial rendering
- Налаштування та best practices
-
React SPA:
- архітектурні рішення — на розробнику
- легко припуститися помилок
-
Next.js:
- opinionated фреймворк
- вбудовані best practices
- швидший старт для продакшену
Коротко:
- React SPA — це лише UI-рівень, Next.js — fullstack-фреймворк
- Next.js підтримує серверний рендеринг та сучасні оптимізації
- Для реальних продакшен-проєктів обирають Next.js
5. Які задачі Next.js вирішує на рівні фронтенду і бекенду?
Next.js позиціонується як fullstack React-фреймворк, оскільки закриває як типові фронтенд-задачі, так і значну частину серверної логіки без потреби в окремому бекенд-проєкті.
- Маршрутизація та навігація
- файлова маршрутизація через
app/ - вкладені маршрути та layouts
- loading / error стани
- клієнтська навігація без перезавантаження сторінки
app/
├─ layout.tsx
├─ page.tsx
└─ dashboard/
└─ page.tsx- Рендеринг та продуктивність
- React Server Components за замовчуванням
- SSR / SSG / ISR
- streaming та partial rendering
- зменшення JS-бандла
- Оптимізації з коробки
- оптимізація зображень (
next/image) - оптимізація шрифтів (
next/font) - автоматичний code splitting
- prefetch навігації
- Керування UI-станами
- loading (
loading.tsx) - error boundaries (
error.tsx) - not found (
not-found.tsx) - metadata для SEO
- Data fetching на сервері
- виконання запитів до API або БД на сервері
- кешування та revalidation через fetch
await fetch(url, { next: { revalidate: 60 } });- API та серверна логіка
- Route Handlers (
app/api/*) - побудова REST або edge-ендпоінтів
- робота без окремого Express / Nest сервера
// app/api/users/route.ts
export async function GET() {
return Response.json({ users: [] });
}- Server Actions
- виклик серверної логіки напряму з компонентів
- обробка форм без клієнтського API
'use server';
export async function createUser(formData: FormData) {
// серверна логіка
}- Middleware
- перевірка авторизації
- редиректи
- геолокація
- A/B логіка
export function middleware(req: Request) {
// auth, redirects, headers
}- Безпека
- доступ до секретів лише на сервері
- відсутність витоку токенів у браузер
- контроль доступу на рівні маршруту
Коротко:
- Next.js закриває фронтенд-задачі: UI, маршрути, оптимізації, SEO
- На бекенді: data fetching, API, server actions, middleware
- Це дозволяє будувати повноцінні fullstack-застосунки в одному проєкті
6. Як Next.js обробляє серверний рендеринг (SSR)?
У Next.js 16+ серверний рендеринг є частиною єдиного гібридного підходу,
побудованого навколо React Server Components та App Router.
SSR означає, що HTML сторінки генерується на сервері при кожному запиті, а
не під час білду.
- Запит від користувача надходить на сервер
- Server Components виконуються на сервері
- Дані отримуються під час рендерингу
- Сервер повертає готовий HTML
- На клієнті відбувається гідратація Client Components
У Next.js 16+ SSR не вмикається явно — він визначається через налаштування кешування.
SSR через fetch з no-store
export default async function Page() {
const data = await fetch('https://api.example.com/data', {
cache: 'no-store',
}).then(res => res.json());
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}cache: 'no-store'→ сторінка рендериться на кожен запит- дані не кешуються
- класичний SSR
SSR також активується, якщо сторінка є динамічною:
export const dynamic = 'force-dynamic';Або якщо використовується:
- cookies
- headers
- auth-сесії
- персоналізовані дані
SSR доцільний, якщо:
- дані часто змінюються
- контент персоналізований
- потрібна актуальність у реальному часі
- залежність від cookies / headers / auth
Приклади:
- dashboard
- профіль користувача
- admin-панель
SSR — рендер на кожен запит SSG — рендер під час білду ISR — статичний рендер + revalidation RSC — базовий механізм виконання на сервері
У Next.js 16+ SSR — це не окремий режим, а частина гібридної моделі.
Важливо
getServerSidePropsне використовується (Pages Router)- SSR у App Router керується через cache та dynamic
useEffectне потрібен для data fetching
Коротко:
- SSR у Next.js 16+ виконується на сервері при кожному запиті
- Вмикається через cache:
'no-store'або динамічний рендеринг - Є частиною гібридної моделі App Router та Server Components
7. У Next.js як зробити так, щоб сторінка рендерилась на сервері при кожному запиті?
У Next.js 16+ сторінка рендериться на сервері при кожному запиті (SSR) не через окремий режим, а через керування кешуванням і динамічністю.
Існує кілька коректних способів це зробити.
- Використати
fetchзcache: 'no-store'(рекомендовано)
Це основний і найпоширеніший спосіб увімкнути SSR у App Router.
export default async function Page() {
const data = await fetch('https://api.example.com/data', {
cache: 'no-store',
}).then(res => res.json());
return <div>{data.title}</div>;
}- сторінка рендериться на кожен запит
- дані не кешуються
- повноцінний SSR
- Примусово зробити сторінку динамічною
Можна явно вказати, що сторінка має бути динамічною:
export const dynamic = 'force-dynamic';Це означає:
- рендер при кожному запиті
- навіть без fetch
- Використання cookies або headers
Якщо сторінка читає:
- cookies()
- headers()
- дані користувача / сесії
→ Next.js автоматично вмикає SSR
import { cookies } from 'next/headers';
export default function Page() {
const token = cookies().get('token');
return <div>{token?.value}</div>;
}getServerSideProps— Pages RouteruseEffectдля SSR- ручне керування сервером
SSR при кожному запиті використовують для:
- персоналізованих сторінок
- dashboard
- admin-панелей
- контенту, що часто змінюється
Коротко:
SSR у Next.js 16+ вмикається через cache: 'no-store' Або через
dynamic = 'force-dynamic' Next.js автоматично рендерить сторінку на сервері,
якщо є cookies / headers
8. Що таке автоматична оптимізація сайтів у Next.js?
Автоматична оптимізація в Next.js — це набір вбудованих механізмів, які
покращують продуктивність, SEO та UX автоматично, без ручної конфігурації.
У Next.js 16+ (App Router) більшість оптимізацій працюють “out of the
box” і вважаються стандартною поведінкою фреймворку.
- Автоматичний вибір стратегії рендерингу
Next.js сам визначає, як рендерити сторінку:
- Static (SSG) — якщо дані кешуються
- ISR — якщо задано
revalidate - SSR — якщо
no-store, cookies або headers - Server Components — за замовчуванням
await fetch(url, { next: { revalidate: 60 } }); // ISR
await fetch(url, { cache: 'no-store' }); // SSRРозробнику не потрібно вручну обирати режим.
- Automatic Code Splitting
Next.js автоматично:
- ділить код по маршрутах
- завантажує лише потрібний JS
- зменшує initial bundle
Це працює без налаштувань, на рівні App Router.
- React Server Components (RSC)
- серверні компоненти не потрапляють у JS-бандл
- логіка та data fetching виконуються на сервері
- менше JavaScript у браузері
export default async function Page() {
const data = await getData();
return <div>{data.title}</div>;
}- Оптимізація зображень (
next/image)
- автоматичний lazy loading
- responsive images
- modern formats (WebP / AVIF)
- оптимальний розмір під девайс
import Image from 'next/image';
<Image src="/hero.png" alt="Hero" width={400} height={300} />- Оптимізація шрифтів (
next/font)
- self-hosted шрифти
- відсутність layout shift
- автоматичний preload
import { Inter } from 'next/font/google';
const inter = Inter({ subsets: ['latin'] });- Prefetch навігації Next.js
- автоматично prefetch-ить маршрути
- швидка навігація без повного перезавантаження
- працює через
<Link />
- Streaming та partial rendering
- HTML віддається частинами
- сторінка починає рендеритись до повного завантаження даних
- покращує TTFB та UX
- Оптимізації вбудовані, а не опціональні
- Next.js заохочує “performance by default”
- Ручна оптимізація потрібна рідко
Коротко:
- Next.js автоматично оптимізує рендеринг, JS та assets
- Server Components і code splitting зменшують бандл
- Зображення, шрифти та навігація оптимізуються з коробки
9. Як працюють змінні середовища в Next.js?
У Next.js 16+ змінні середовища використовуються для зберігання
конфігурації, секретів та середовищних налаштувань.
Ключовий принцип — чітке розділення серверних і клієнтських змінних.
- Файли зі змінними середовища
Next.js автоматично підхоплює такі файли:
.env.local— локальне середовище (не комітиться).env.development.env.production.env.test
DATABASE_URL=postgres://...
NEXT_PUBLIC_API_URL=https://api.example.com- Серверні змінні середовища (за замовчуванням)
Змінні без префікса NEXT_PUBLIC_:
- доступні лише на сервері
- не потрапляють у JS-бандл
- безпечні для зберігання секретів
const dbUrl = process.env.DATABASE_URL;Можна використовувати в:
- Server Components
- Route Handlers
- Server Actions
- Middleware
- Клієнтські змінні середовища
Змінні з префіксом NEXT_PUBLIC_:
- доступні в браузері
- інжектяться під час білду
- не є секретами
const apiUrl = process.env.NEXT*PUBLIC_API_URL;Усі NEXT_PUBLIC_* значення видимі користувачу.
- Використання в App Router
Server Component (безпечний доступ)
export default function Page() {
return <div>{process.env.SECRET_KEY}</div>;
}Client Component (тільки NEXT_PUBLIC_*)
'use client';
export default function ClientComp() {
return <div>{process.env.NEXT_PUBLIC_API_URL}</div>;
}- Важливі особливості
- Змінні читаються під час білду
- Зміна
.env→ потрібен restart сервера - Runtime-змінні підтримуються лише на сервері
- Edge Middleware має обмежений доступ
- Використання секретів з
NEXT_PUBLIC_ - Доступ до server env у Client Component
- Очікування, що env зміниться без рестарту
Коротко:
- Змінні без
NEXT_PUBLIC_— тільки серверні NEXT_PUBLIC_*— доступні в браузері- У Next.js 16+ безпека базується на поділі server / client
10. Яка різниця між клієнтським та серверним рендерингом у Next.js?
У Next.js 16+ клієнтський і серверний рендеринг — це не взаємовиключні підходи, а частини гібридної архітектури, побудованої навколо React Server Components та App Router.
- HTML генерується на сервері
- Дані отримуються під час рендерингу
- У браузер надходить готова розмітка
- Клієнтські компоненти гідратуються після завантаження
- Server Components — за замовчуванням
- Підтримуються SSR / SSG / ISR
- Data fetching виконується на сервері
export default async function Page() {
const data = await fetch('https://api.example.com/data', {
cache: 'no-store',
}).then(res => res.json());
return <div>{data.title}</div>;
}- кращий SEO
- швидший first paint
- менший JS-бандл
- безпечна робота з БД і секретами
Як працює
- HTML мінімальний або порожній
- Дані завантажуються в браузері
- UI рендериться після виконання JavaScript
У Next.js 16+
- Реалізується через Client Components
- Потрібна директива 'use client'
'use client';
import { useEffect, useState } from 'react';
export default function ClientComponent() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(setData);
}, []);
return <div>{data?.title}</div>;
}- інтерактивні елементи
- робота з browser-only API
- локальний UI-стан
- Server Rendering — база за замовчуванням
- Client Rendering використовується точково
- Server + Client компоненти комбінуються в одному дереві
Коротко:
- У Next.js 16+ серверний рендеринг — стандарт
- Клієнтський рендеринг потрібен лише для інтерактивності
- Оптимальний підхід — мінімум Client Components, максимум Server Components
11. Як працює файловий роутинг у Next.js?
У Next.js файловий роутинг реалізований через App Router і базується на
структурі папки app/.
Кожна папка та спеціальний файл визначають маршрут, layout або поведінку
сторінки без ручної конфігурації.
page.tsx— сторінка маршруту
Файл page.tsx створює публічний маршрут.
app/page.tsx → /
app/blog/page.tsx → /blogexport default function Page() {
return <h1>Blog</h1>;
}layout.tsx— спільний layout
layout.tsx обгортає всі вкладені сторінки:
app/layout.tsx → кореневий layout
app/dashboard/layout.tsx → layout для /dashboard/*export default function Layout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>{children}</body>
</html>
);
}- Вкладені маршрути (Nested Routes)
Структура папок визначає вкладеність маршрутів:
app/dashboard/settings/page.tsx → /dashboard/settings- Динамічні маршрути
Для параметрів використовуються квадратні дужки:
app/posts/[id]/page.tsx → /posts/123export default function Page({ params }: { params: { id: string } }) {
return <div>Post {params.id}</div>;
}- Спеціальні файли маршруту
| Файл | Призначення |
|---|---|
loading.tsx |
loading state |
error.tsx |
error boundary |
not-found.tsx |
404 |
template.tsx |
reset state між навігаціями |
- Route Groups
Папки в дужках не впливають на URL, але допомагають структурувати код:
app/(auth)/login/page.tsx → /login- Приватні папки
Папки з _ не створюють маршрут:
app/_components/- Маршрути створюються автоматично
- Немає конфігурації роутів
- App Router підтримує streaming та layouts
- Pages Router використовується лише для legacy-проєктів
Коротко:
- Файловий роутинг у Next.js 16+ базується на папці
app/ page.tsxстворює маршрут,layout.tsx— спільний UI- Динамічні маршрути та спеціальні файли керують поведінкою сторінки
12. Як створювати динамічні маршрути в Next.js?
У Next.js динамічні маршрути створюються за допомогою квадратних дужок
([]) у структурі папок app/.
Це дозволяє будувати сторінки з параметрами URL без ручної конфігурації
роутів.
- Базовий динамічний маршрут
app/posts/[id]/page.tsx → /posts/123export default function Page({ params }: { params: { id: string } }) {
return <div>Post ID: {params.id}</div>;
}- id — параметр маршруту
- значення доступне через params
- Кілька параметрів
app/users/[userId]/posts/[postId]/page.tsx
→ /users/42/posts/7export default function Page({
params,
}: {
params: { userId: string; postId: string };
}) {
return (
<div>
User: {params.userId}, Post: {params.postId}
</div>
);
}- Catch-all маршрути
Використовуються для змінної кількості сегментів.
app/docs/[...slug]/page.tsx
→ /docs/a/b/cexport default function Page({ params }: { params: { slug: string[] } }) {
return <div>{params.slug.join('/')}</div>;
}- Optional catch-all маршрути
app/docs/[[...slug]]/page.tsxПрацює для:
/docs/docs/a/docs/a/b
- Data fetching у динамічних маршрутах
export default async function Page({ params }: { params: { id: string } }) {
const post = await fetch(`https://api.example.com/posts/${params.id}`, {
cache: 'no-store',
}).then(res => res.json());
return <h1>{post.title}</h1>;
}- Генерація статичних маршрутів (SSG)
Для SSG використовують generateStaticParams:
export async function generateStaticParams() {
return [{ id: '1' }, { id: '2' }];
}- Використовувати Server Components за замовчуванням
- Валідувати параметри
- Не зловживати catch-all маршрутами
- Поєднувати з layouts для спільного UI
Коротко:
- Динамічні маршрути створюються через
[param] paramsмістить значення URL- Підтримуються catch-all та optional маршрути
- Працює з SSR, SSG та ISR
13. Як Next.js обробляє параметри URL у динамічних маршрутах?
У Next.js параметри URL у динамічних маршрутах обробляються автоматично
через структуру папок у app/.
Значення параметрів передаються в сторінку або layout через обʼєкт params.
- Доступ до параметрів маршруту
Для маршруту:
app/posts/[id]/page.tsx → /posts/123Next.js передає параметри як проп:
export default function Page({ params }: { params: { id: string } }) {
return <div>Post ID: {params.id}</div>;
}idзавжди типуstring- отримується на сервері
- Параметри в layouts
Параметри доступні не лише в page.tsx, а й у вкладених layout.tsx:
export default function Layout({
children,
params,
}: {
children: React.ReactNode;
params: { id: string };
}) {
return (
<section>
<h1>Post {params.id}</h1>
{children}
</section>
);
}- Catch-all параметри
app/docs/[...slug]/page.tsx → /docs/a/b/cexport default function Page({ params }: { params: { slug: string[] } }) {
return <div>{params.slug.join('/')}</div>;
}slug— масив сегментів URL
- Optional catch-all параметри
app/docs/[[...slug]]/page.tsxparams.slug; // string[] | undefinedПрацює для:
/docs/docs/a/docs/a/b
- Параметри та data fetching
Параметри часто використовуються для серверного data fetching:
export default async function Page({ params }: { params: { id: string } }) {
const data = await fetch(`https://api.example.com/posts/${params.id}`, {
cache: 'no-store',
}).then(res => res.json());
return <h1>{data.title}</h1>;
}- Валідація параметрів
Next.js не валідовує параметри автоматично, тому:
- перевірка типів
- обробка невалідних значень
- виклик
notFound()
import { notFound } from 'next/navigation';
if (!isValid(params.id)) {
notFound();
}paramsдоступні лише на сервері- У Client Components параметри отримують через
useParams() - Параметри завжди рядки або масиви рядків
Коротко:
- URL-параметри передаються через
params - Працюють у
page.tsxіlayout.tsx - Підтримуються dynamic, catch-all і optional параметри
- Валідація параметрів — відповідальність розробника
14. Як обробляти маршрути catch-all у Next.js?
У Next.js 16+ catch-all маршрути дозволяють обробляти змінну кількість
сегментів URL в одному маршруті.
Вони реалізуються через спеціальний синтаксис папок у директорії app/.
- Catch-all маршрути (
[...param])
Catch-all маршрут обробляє один або більше сегментів URL.
app/docs/[...slug]/page.tsxВідповідає URL:
/docs/a/docs/a/b/docs/a/b/c
export default function Page({ params }: { params: { slug: string[] } }) {
return <div>{params.slug.join('/')}</div>;
}slug— масив рядків- завжди містить щонайменше один елемент
- Optional catch-all маршрути (
[[...param]])
Optional catch-all дозволяє обробляти нуль або більше сегментів.
app/docs/[[...slug]]/page.tsxВідповідає URL:
/docs/docs/a/docs/a/b
export default function Page({ params }: { params: { slug?: string[] } }) {
return <div>{params.slug?.join('/') ?? 'Docs root'}</div>;
}- Різниця між catch-all і optional catch-all
| Тип | Сегменти | Значення |
|---|---|---|
[...slug] |
1+ | string[] |
[[...slug]] |
0+ | string[] / undefined |
- Типові кейси використання
Catch-all маршрути застосовують для:
- документації
- блогів з вкладеною структурою
- файлових менеджерів
- CMS-сторінок
- breadcrumbs-навігації
- Data fetching з catch-all
export default async function Page({
params,
}: {
params: { slug?: string[] };
}) {
const path = params.slug?.join('/') ?? '';
const page = await fetch(`https://api.example.com/pages/${path}`, {
cache: 'no-store',
}).then(res => res.json());
return <h1>{page.title}</h1>;
}- Використовувати catch-all лише за потреби
- Обробляти edge cases (
undefined) - Поєднувати з layouts
- Валідувати сегменти URL
Коротко:
- Catch-all маршрути обробляють змінну кількість сегментів
[...param]— мінімум один сегмент[[...param]]— нуль або більше сегментів- Часто використовуються для docs та CMS
15. Опиши функціональність компонента Link у Next.js.
Компонент Link у Next.js використовується для клієнтської навігації
між маршрутами без повного перезавантаження сторінки.
Він є ключовим елементом App Router та забезпечує швидку й оптимізовану
навігацію.
- Клієнтська навігація (SPA-поведінка)
Link виконує перехід між сторінками:
- без перезавантаження браузера
- зі збереженням стану
- з мінімальним JS-навантаженням
import Link from 'next/link';
<Link href="/blog">Blog</Link>;- Автоматичний prefetch
Next.js автоматично prefetch-ить сторінки, на які веде Link:
- при появі у viewport
- у фоновому режимі
- тільки для внутрішніх маршрутів
Це значно прискорює навігацію.
- Інтеграція з App Router
Link працює з:
- nested routes
- layouts
- streaming
- loading states
Навігація не скидає layouts і не викликає повний ререндер сторінки.
- Підтримка динамічних маршрутів
<Link href={`/posts/${id}`}>Post</Link>Працює з dynamic та catch-all маршрутами.
- Accessibility (a11y)
Linkрендерить<a>- підтримує клавіатурну навігацію
- коректно працює з screen readers
- використовувати
<a href>для внутрішньої навігації - обгортати
Linkв<a> - вручну реалізовувати SPA-навігацію
prefetch={false}— вимкнення prefetchreplace— замінює запис у historyscroll={false}— зберігає позицію скролу
<Link href="/dashboard" prefetch={false} scroll={false}>
Dashboard
</Link>Коротко:
Linkзабезпечує швидку клієнтську навігацію- Автоматично prefetch-ить сторінки
- Глибоко інтегрований з App Router та layouts
- Є стандартом навігації у Next.js
16. Як реалізувати міжсторінкову навігацію (navigation) у Next.js?
У Next.js міжсторінкова навігація реалізується через вбудований router App Router, який підтримує декларативну та програмну навігацію без перезавантаження сторінки.
- Декларативна навігація через
Link(основний спосіб)
Компонент Link використовується для навігації через UI:
import Link from 'next/link';
<Link href="/blog">Blog</Link>;Коли використовувати:
- навігаційні меню
- списки
- кнопки-посилання
- Програмна навігація через
useRouter
Для навігації у відповідь на події (submit, click, success):
'use client';
import { useRouter } from 'next/navigation';
export default function Form() {
const router = useRouter();
const onSubmit = async () => {
await saveData();
router.push('/dashboard');
};
return <button onClick={onSubmit}>Save</button>;
}Основні методи:
router.push()— перехідrouter.replace()— без historyrouter.back()— назадrouter.refresh()— оновлення даних
- Навігація після Server Actions
У Server Actions використовується redirect():
'use server';
import { redirect } from 'next/navigation';
export async function createPost() {
// логіка
redirect('/posts');
}- Керування URL без навігації
Для читання параметрів URL:
useParams()useSearchParams()
'use client';
import { useSearchParams } from 'next/navigation';
const params = useSearchParams();next/router(Pages Router)- ручну роботу з
window.location
Link— для UI-навігаціїuseRouter— для подійredirect— для серверної логіки- мінімізувати Client Components
Коротко:
- Next.js підтримує декларативну та програмну навігацію
Link— основний інструментuseRouterтаredirect— для керування навігацією з логіки
17. Як працює попереднє завантаження сторінок (prefetching) у Next.js?
У Next.js попереднє завантаження сторінок (prefetching) — це
автоматичний механізм, який завантажує дані та код сторінки заздалегідь, ще
до переходу користувача.
Це забезпечує миттєву навігацію між сторінками.
- Компонент
<Link />зʼявляється у viewport - Next.js у фоновому режимі:
- завантажує потрібний JavaScript
- отримує серверні дані (RSC payload)
- При кліку сторінка відкривається майже миттєво
Все відбувається без перезавантаження сторінки.
- Увімкнений за замовчуванням
- Працює тільки для внутрішніх маршрутів
- Використовує React Server Components
- Враховує кешування (
fetch,revalidate)
import Link from 'next/link';
<Link href="/dashboard">Dashboard</Link>;- JS-код сторінки
- RSC-дані
- Layout-и, які ще не були завантажені
Не prefetch-яться:
- зовнішні посилання
- сторінки з prefetch={false}
Вимкнення prefetch
<Link href="/heavy-page" prefetch={false}>
Heavy page
</Link>Коли варто вимикати:
- важкі сторінки
- рідко використовувані маршрути
- сторінки з персональними даними
Плюси:
- швидша навігація
- кращий UX
- менший TTI
Мінуси:
- додаткові фонові запити
- потенційне навантаження на сервер
- Довіряти default-поведінці
- Не вимикати без причини
- Поєднувати з Server Components та кешуванням
Коротко:
- Prefetching автоматично підвантажує сторінки
- Активується через Link
- Значно пришвидшує навігацію
- Може бути вимкнений для окремих маршрутів
18. Як Next.js реалізує code splitting?
У Next.js code splitting реалізований автоматично та є частиною
філософії performance by default.
Розробнику не потрібно вручну налаштовувати поділ коду — Next.js робить це
на рівні маршрутизації та компонентів.
- Code splitting за маршрутами
Кожен маршрут (page.tsx) отримує окремий JS-бандл:
app/page.tsx → bundle для /
app/blog/page.tsx → bundle для /blogЗавантажується лише код потрібної сторінки.
- Code splitting через React Server Components
- Server Components не потрапляють у JS-бандл
- Логіка та data fetching виконуються на сервері
- У браузер передається лише результат
export default async function Page() {
const data = await getData();
return <div>{data.title}</div>;
}Це суттєво зменшує розмір клієнтського JavaScript.
- Code splitting для Client Components
Client Components:
- виділяються в окремі чанки
- завантажуються лише за потреби
- ізольовані від серверної логіки
'use client';
export function InteractiveButton() {
return <button>Click</button>;
}- Динамічний імпорт (next/dynamic)
Для важких або рідко використовуваних компонентів:
import dynamic from 'next/dynamic';
const HeavyChart = dynamic(() => import('./HeavyChart'), {
ssr: false,
});Код завантажиться тільки коли компонент реально потрібен.
- Next.js prefetch-ить чанки для наступних сторінок
- При кліку чанки вже в кеші
- Навігація виглядає миттєвою
- вручну налаштовувати Webpack
- розбивати код вручну без потреби
- імпортувати великі бібліотеки у Client Components
- Максимально використовувати Server Components
- Мінімізувати
use client - Використовувати dynamic import для важких UI
- Довіряти автоматичному code splitting
Коротко:
- Code splitting у Next.js 16+ працює автоматично
- Поділ відбувається за маршрутами та компонентами
- Server Components суттєво зменшують JS-бандл
- Dynamic imports — для важких або опційних частин UI
19. Як Next.js оптимізує початкове завантаження сторінки?
У Next.js 16+ оптимізація початкового завантаження сторінки — це результат поєднання кількох автоматичних механізмів, які зменшують час до першого рендеру та покращують UX.
- Server Components за замовчуванням
- більшість компонентів виконуються на сервері
- у браузер потрапляє мінімум JavaScript
- швидший First Contentful Paint (FCP)
export default async function Page() {
const data = await getData();
return <div>{data.title}</div>;
}- Автоматичний code splitting
- JS ділиться по маршрутах
- завантажується тільки потрібний код
- зменшення initial bundle
- Streaming та partial rendering
- HTML віддається частинами
- UI зʼявляється ще до завершення всіх запитів
- користувач бачить контент швидше
- Prefetching навігації
- наступні сторінки підвантажуються у фоні
- навігація відбувається майже миттєво
- Оптимізація зображень
next/image:
- lazy loading
- адаптивні розміри
- сучасні формати (AVIF / WebP)
- Оптимізація шрифтів
next/font:
- self-hosted
- preload
- без CLS
- Кешування та revalidation
- контроль кешу через
fetch - SSG / ISR зменшують кількість SSR
- швидка доставка контенту
- вручну оптимізувати бандл
- писати кастомний SSR
- налаштовувати CDN
- Використовувати Server Components
- Мінімізувати Client Components
- Не вимикати prefetch без потреби
- Правильно керувати кешуванням
Коротко:
- Next.js мінімізує JS за рахунок Server Components
- Code splitting і streaming прискорюють рендер
- Зображення та шрифти оптимізуються автоматично
- Більшість оптимізацій працює з коробки
20. Які підходи до data fetching підтримує Next.js?
У Next.js 16+ data fetching є частиною серверного рендерингу та тісно
інтегрований з React Server Components.
Основний інструмент — вбудований fetch, розширений механізмами кешування
та revalidation.
- Server-side data fetching (SSR)
Дані отримуються на кожен запит.
await fetch(url, { cache: 'no-store' });Коли використовувати:
- персоналізований контент
- auth-залежні сторінки
- дані, що часто змінюються
- Static data fetching (SSG)
Дані отримуються під час білду і кешуються.
await fetch(url);Коли використовувати:
- публічні сторінки
- рідко змінюваний контент
- максимальний performance і SEO
- Incremental Static Regeneration (ISR)
Статичні сторінки з оновленням по таймеру.
await fetch(url, { next: { revalidate: 60 } });Коли використовувати:
- блоги
- каталоги
- контент, що оновлюється періодично
- Data fetching у Server Components (default)
Server Components:
- виконуються на сервері
- не потрапляють у JS-бандл
- можуть напряму звертатись до БД або API
export default async function Page() {
const data = await getData();
return <div>{data.title}</div>;
}- Client-side data fetching
Використовується лише для інтерактивних сценаріїв.
'use client';
import { useEffect, useState } from 'react';
export function ClientData() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(setData);
}, []);
return <div>{data}</div>;
}Коли використовувати:
- real-time UI
- browser-only API
- локальний стан
- Data fetching через Route Handlers
Для побудови API всередині Next.js:
// app/api/posts/route.ts
export async function GET() {
return Response.json({ posts: [] });
}fetchу Next.js кешується за замовчуванням- Кеш керується через
cacheтаrevalidate useEffectне є основним підходом- Server Components — пріоритет
Коротко:
- Next.js підтримує SSR, SSG, ISR і client fetching
- Основний підхід — data fetching у Server Components
- Кешування та revalidation керують поведінкою
- Правильний вибір стратегії критичний для performance
21. Що таке getStaticProps і коли його варто використовувати?
getStaticProps — це функція з Pages Router, яка використовувалась для
Static Site Generation (SSG), тобто генерації сторінок під час білду.
У Next.js з App Router getStaticProps не використовується. Він вважається
legacy API і застосовується лише для підтримки старих проєктів.
export async function getStaticProps() {
const data = await fetchData();
return {
props: { data },
};
}- виконувався під час білду
- дані передавались у компонент сторінки
- сторінка ставала статичною
- підтримував ISR через revalidate
У App Router всі ці задачі вирішуються простіше та гнучкіше:
Заміна getStaticProps у Next.js
await fetch(url); // SSG за замовчуваннямawait fetch(url, { next: { revalidate: 60 } }); // ISR- data fetching виконується напряму в компоненті
- немає окремих lifecycle-функцій
- працює з Server Components
- менше boilerplate-коду
- у старих проєктах на Pages Router
- під час міграції на App Router
- у legacy-коді
Не використовують у нових проєктах
Коротко:
getStaticProps— legacy API Pages Router- У Next.js 16+ не використовується
- Заміна —
fetchу Server Components - Для нових проєктів обирають App Router
22. Що таке getServerSideProps і який тип рендерингу він дозволяє?
getServerSideProps — це функція з Pages Router, яка використовувалась
для реалізації Server-Side Rendering (SSR), тобто рендерингу сторінки на
сервері при кожному запиті.
У Next.js з App Router getServerSideProps не використовується. Це legacy
API, актуальне лише для підтримки старих проєктів.
export async function getServerSideProps(context) {
const data = await fetchData(context);
return {
props: { data },
};
}- виконувався на кожен HTTP-запит
- мав доступ до
req,res, cookies, headers - забезпечував SSR
- сторінка не кешувалась за замовчуванням
Server-Side Rendering (SSR)
- HTML генерується при кожному запиті
- підходить для персоналізованого контенту
- актуальні дані на момент запиту
У App Router SSR реалізується без окремих lifecycle-функцій — через керування кешуванням:
await fetch(url, { cache: 'no-store' });Або примусово:
export const dynamic = 'force-dynamic';Переваги нового підходу:
- data fetching прямо в Server Components
- менше boilerplate-коду
- інтеграція з React Server Components
- краща продуктивність і гнучкість
- у legacy-проєктах
- під час міграції з Pages Router
- у старих навчальних матеріалах
Не використовується в нових проєктах
Коротко:
getServerSidePropsдозволяв SSR у Pages Router- Виконувався на кожен запит
- У Next.js 16+ не використовується
- Заміна — SSR через
fetchі динамічний рендеринг в App Router
23. Як реалізувати інкрементальну статичну регенерацію (ISR) у Next.js?
У Next.js Incremental Static Regeneration (ISR) дозволяє поєднати
швидкість статичних сторінок з можливістю оновлювати дані без повного
ребілду.
ISR реалізується через керування кешуванням fetch в App Router.
- Базова реалізація ISR
Щоб увімкнути ISR, потрібно вказати час revalidation у fetch:
await fetch('https://api.example.com/posts', {
next: { revalidate: 60 },
});- сторінка генерується статично
- кеш оновлюється раз на 60 секунд
- користувачі завжди отримують швидкий HTML
- ISR у Server Components
ISR використовується без окремих функцій, напряму в компоненті:
export default async function Page() {
const posts = await fetch(
'https://api.example.com/posts',
{ next: { revalidate: 300 } }
).then(res => res.json());
return <PostsList posts={posts} />;
}- ISR для динамічних маршрутів
Для динамічних сторінок ISR поєднується з generateStaticParams:
export async function generateStaticParams() {
return [{ id: '1' }, { id: '2' }];
}
await fetch(url, { next: { revalidate: 60 } });- On-demand revalidation (опціонально)
Next.js підтримує ручне оновлення кешу через Route Handlers:
import { revalidatePath } from 'next/cache';
revalidatePath('/blog');Використовується для:
- CMS
- адмін-панелей
- webhooks
- Коли використовувати ISR
ISR доцільний, якщо:
- контент змінюється нечасто
- важлива швидкість
- небажаний повний rebuild
Приклади:
- блоги
- каталоги
- маркетингові сторінки
Коротко:
- ISR реалізується через fetch з revalidate
- Працює у Server Components
- Підходить для контенту, що оновлюється періодично
- Не потребує окремих lifecycle-функцій
24. Чи можна виконувати client-side data fetching у Next.js?
Так, у Next.js client-side data fetching можливий, але він не є основним
підходом.
Next.js побудований навколо Server Components, тому клієнтське отримання
даних використовується лише для специфічних сценаріїв.
Client-side data fetching можливий тільки в Client Components, які
позначаються директивою 'use client'.
'use client';
import { useEffect, useState } from 'react';
export default function ClientData() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(setData);
}, []);
return <div>{data?.title}</div>;
}Коли client-side data fetching доцільний
- real-time оновлення (polling, WebSocket)
- робота з browser-only API
- локальний UI-стан
- інтерактивні фільтри / пошук
Коли не варто використовувати
- для SEO-критичного контенту
- для початкового рендеру сторінки
- для доступу до секретів
- для основних даних сторінки
- Мінімізувати
use client - Не дублювати server data fetching
- Поєднувати з Server Components
- Використовувати Route Handlers для API
Коротко:
- Client-side data fetching підтримується
- Використовується лише у Client Components
- Підходить для інтерактивних сценаріїв
- Основний підхід у Next.js 16+ — server-side data fetching
25. Поясни різницю між useEffect та getStaticProps.
useEffect і getStaticProps — це принципово різні механізми, які працюють
у різних середовищах і вирішують різні задачі.
useEffect — це React-хук, який виконується на клієнті після рендеру
компонента.
'use client';
import { useEffect, useState } from 'react';
export default function ClientComponent() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(setData);
}, []);
return <div>{data}</div>;
}- виконується в браузері
- працює після першого рендеру
- не впливає на HTML, який отримує пошуковий робот
- підходить для інтерактивних сценаріїв
getStaticProps — це API Pages Router, яке використовувалось для Static Site
Generation (SSG).
export async function getStaticProps() {
const data = await fetchData();
return {
props: { data },
};
}- виконувався на сервері під час білду
- генерував статичний HTML
- забезпечував SEO
- не використовується в Next.js 16+ (App Router)
У App Router обидва кейси замінюються data fetching у Server Components:
export default async function Page() {
const data = await fetch('https://api.example.com/data').then(res =>
res.json()
);
return <div>{data.title}</div>;
}- серверний рендеринг
- SEO
- мінімум JS
- без
useEffectіgetStaticProps
Коротко:
useEffect— клієнтський хук після рендеруgetStaticProps— server-side SSG (Pages Router)- У Next.js 16+ обидва замінені data fetching у Server Components
26. Як створити API-роут у Next.js?
У Next.js 16+ API-роути реалізуються через Route Handlers, які
розміщуються в директорії app/api.
Це сучасна заміна pages/api/* і стандартний підхід у App Router.
- Створення API-роуту (Route Handler)
API-роут створюється файлом route.ts або route.js.
app/api/posts/route.ts// app/api/posts/route.ts
export async function GET() {
return Response.json({ posts: [] });
}Маршрут буде доступний за адресою:
GET /api/posts- Підтримка HTTP-методів
Route Handlers підтримують стандартні HTTP-методи:
GETPOSTPUTPATCHDELETE
export async function POST(request: Request) {
const body = await request.json();
return Response.json(
{ success: true, body },
{ status: 201 }
);
}- Отримання параметрів та headers
Query parameters:
export async function GET(request: Request) { const { searchParams } = new URL(request.url); const page = searchParams.get('page');
return Response.json({ page }); }
Headers / cookies: import { headers, cookies } from 'next/headers';
const token = cookies().get('token'); const userAgent = headers().get('user-agent');
- Динамічні API-роути
app/api/posts/[id]/route.tsexport async function GET(
_: Request,
{ params }: { params: { id: string } }
) {
return Response.json({ id: params.id });
}- Типові кейси використання
- REST API
- backend-for-frontend (BFF)
- проксі до зовнішніх API
- on-demand revalidation
- auth-ендпоінти
- Використовувати Route Handlers замість Pages API
- Тримати API-логику серверною
- Не повертати секрети
- Поєднувати з Server Actions для мутацій
Коротко:
- API-роути в Next.js 16+ створюються через app/api/*/route.ts
- Підтримуються всі основні HTTP-методи
- Це сучасна заміна pages/api
- Route Handlers — стандарт для бекенд-логіки в App Router
27. Поясни, як обробляти параметри запиту (query parameters) в API-роутах Next.js.
У Next.js 16+ параметри запиту (query parameters) в API-роутах
обробляються через обʼєкт Request, який відповідає стандарту Web Fetch
API.
Next.js не використовує власний API для query — усе базується на URL та
URLSearchParams.
- Отримання query parameters
У Route Handler доступний обʼєкт Request, з якого можна отримати URL:
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const page = searchParams.get('page');
const limit = searchParams.get('limit');
return Response.json({ page, limit });
}- Параметри з дефолтними значеннями
const page = Number(searchParams.get('page') ?? 1);
const limit = Number(searchParams.get('limit') ?? 10);- Кілька значень одного параметра
/api/posts?tag=js&tag=nextconst tags = searchParams.getAll('tag');- Обробка та валідація параметрів
Next.js не валідовує query parameters автоматично, тому:
if (!page || page < 1) {
return Response.json(
{ error: 'Invalid page' },
{ status: 400 }
);
}- Використання з динамічними API-роутами
Query parameters працюють разом із динамічними сегментами:
app/api/posts/[id]/route.tsexport async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
const { searchParams } = new URL(request.url);
const includeComments = searchParams.get('comments');
return Response.json({
id: params.id,
includeComments,
});
}- Завжди валідовувати query parameters
- Перетворювати типи (string → number)
- Не довіряти значенням з URL
- Повернути коректні HTTP-статуси
Коротко:
- Query parameters обробляються через Request та URLSearchParams
- Підтримуються множинні значення
- Валідація — відповідальність розробника
- Це стандартний Web API підхід у Next.js 16+
28. Як Next.js працює з HTTP-методами в API-роутах?
У Next.js 16+ API-роути реалізуються через Route Handlers
(app/api/**/route.ts), де кожен HTTP-метод описується окремою експортованою
функцією.
Це відповідає стандартам Web Fetch API і робить API-логіку декларативною та
зрозумілою.
- Підтримувані HTTP-методи
Route Handlers підтримують основні методи:
GET— отримання данихPOST— створення ресурсуPUT— повне оновленняPATCH— часткове оновленняDELETE— видалення
- Базовий приклад з кількома методами
// app/api/posts/route.ts
export async function GET() {
return Response.json({ posts: [] });
}
export async function POST(request: Request) {
const body = await request.json();
return Response.json({ created: true, body }, { status: 201 });
}URL:
/api/posts- Динамічні API-роути з методами
app/api/posts/[id]/route.tsexport async function GET(
\_: Request, { params }: { params: { id: string } }
) {
return Response.json({ id: params.id });
}
export async function DELETE(
\_: Request, { params }: { params: { id: string } }
) {
return Response.json({ deleted: params.id });
}- Обробка тіла запиту (body)
request.json()— для JSONrequest.formData()— для формrequest.text()— для plain text
export async function PATCH(request: Request) {
const data = await request.json();
return Response.json({ updated: data });
}- HTTP-статуси та заголовки
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { 'Content-Type': 'application/json' },
});- Кешування та методи
GETможе кешуватись (SSG / ISR)POST,PUT,PATCH,DELETE— завжди динамічні- Мутації не кешуються
- Розділяти логіку по HTTP-методах
- Повертати коректні статуси
- Валідовувати вхідні дані
- Тримати API-роути тонкими (BFF-підхід)
- Для мутацій з UI розглядати Server Actions
Коротко:
- HTTP-методи описуються окремими експортами (
GET,POST, тощо) - Route Handlers відповідають стандарту Fetch API
GET— для читання, інші — для мутацій- Це сучасний і рекомендований підхід у Next.js 16+
29. Як підключити CSS-модулі у застосунку Next.js?
У Next.js CSS-модулі — це вбудований і рекомендований спосіб локальної
стилізації компонентів.
Вони забезпечують scope стилів на рівні компонента, уникаючи конфліктів
класів.
- Створення CSS-модуля
CSS-модуль — це файл з суфіксом .module.css:
components/
├─ Button.tsx
└─ Button.module.css/* Button.module.css */
.button {
background: black;
color: white;
padding: 8px 16px;
}- Підключення CSS-модуля в компоненті
import styles from './Button.module.css';
export function Button() {
return <button className={styles.button}>Click</button>;
}styles.button— унікальний згенерований клас- конфлікти імен класів виключені
- Де можна використовувати CSS-модулі
CSS-модулі можна використовувати:
- у Server Components
- у Client Components
- у будь-яких React-компонентах
Вони не залежать від 'use client'.
- CSS-модулі та App Router
У App Router:
- CSS-модулі імпортуються напряму в компоненти
- не потребують глобальної реєстрації
- автоматично оптимізуються та tree-shake-яться
- Комбінація з іншими стилями
import clsx from 'clsx';
import styles from './Card.module.css';
<div className={clsx(styles.card, styles.active)} />;- Обмеження CSS-модулів
- не можна використовувати для глобальних стилів
- не підходять для reset або typography
- не працюють у
globals.css
Для глобальних стилів використовується app/globals.css.
- CSS-модулі — для компонентних стилів
globals.css— лише для глобальних правил- Тримати стилі поруч з компонентом
- Не змішувати CSS-модулі з inline-стилями без потреби
Коротко:
- CSS-модулі підключаються через
.module.css - Забезпечують локальний scope стилів
- Працюють у Server та Client Components
- Це стандартний спосіб компонентної стилізації в Next.js 16+
30. Чи можна використовувати глобальні стилі в Next.js? Як саме?
Так, у Next.js 16+ глобальні стилі підтримуються, але їх використання
строго регламентоване архітектурою App Router.
Глобальні стилі застосовуються лише для базових правил, а не для стилізації
компонентів.
- Файл глобальних стилів
Глобальні стилі оголошуються у файлі globals.css.
app/
├─ layout.tsx
├─ page.tsx
└─ globals.css- Підключення глобальних стилів
Глобальні стилі імпортуються один раз у кореневому layout:
// app/layout.tsx
import './globals.css';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html>
<body>{children}</body>
</html>
);
}Імпорт можливий тільки у layout або entry-файлах, не в компонентах.
- Що варто писати в глобальних стилях
Глобальні стилі підходять для:
- CSS reset / normalize
- базової typography
- змінних (
:root) - тем (dark / light)
- стилів для
body,html
/* app/globals.css */
:root {
--primary: #000;
}
body {
margin: 0;
font-family: system-ui;
}- Що не варто писати в глобальних стилях
- стилі конкретних компонентів
- utility-класи для UI
- логіку, яку можна ізолювати
Для цього використовують:
- CSS-модулі
- Tailwind CSS
- CSS-in-JS (обмежено)
- Глобальні стилі та App Router
- застосовуються до всього застосунку
- автоматично оптимізуються
- працюють у Server та Client Components
- не потребують 'use client'
- Мінімальний обсяг глобальних стилів
- Компонентні стилі — через CSS-модулі або Tailwind
- Не імпортувати глобальні стилі в компонентах
Коротко:
- Глобальні стилі підтримуються в Next.js 16+
- Підключаються через
app/globals.css - Імпортуються лише в
layout.tsx - Використовуються для базових, а не компонентних стилів
31. Порівняй CSS-in-JS та традиційний CSS у контексті Next.js.
У Next.js підтримуються обидва підходи до стилізації — як традиційний CSS, так і CSS-in-JS, але з різним рівнем доцільності та обмеженнями, особливо в контексті Server Components.
До традиційного CSS у Next.js належать:
- CSS-модулі (
.module.css) - глобальні стилі (
globals.css)
- працює у Server Components за замовчуванням
- не потребує
'use client' - мінімальний runtime-overhead
- краща продуктивність та менший JS-бандл
- офіційно рекомендований підхід
- менша динамічність стилів
- логіку умовної стилізації потрібно вирішувати через класи
CSS-in-JS (наприклад, styled-components, emotion):
- стилі описуються безпосередньо в JavaScript
- часто залежать від props та стану
- потребує Client Components
- додає JS у бандл
- складніша інтеграція з Server Components
- може вимагати додаткового налаштування для SSR
- висока динамічність стилів
- зручна умовна стилізація
- стилі тісно повʼязані з логікою компонента
- не підходить для Server Components
- збільшує initial JS
- ускладнює архітектуру App Router
- CSS-модулі — для компонентних стилів
- globals.css — для базових стилів
- CSS-in-JS — лише за необхідності динамічних стилів
- не використовувати CSS-in-JS без чіткої причини
Коротко:
- Традиційний CSS краще інтегрований з App Router
- CSS-in-JS вимагає Client Components і збільшує JS
- У Next.js 16+ рекомендовано мінімізувати CSS-in-JS
32. Як інтегрувати CSS-фреймворки на кшталт Tailwind CSS v4 у Next.js-проєкт?
У Next.js 16+ інтеграція Tailwind CSS v4 є максимально простою та
добре узгоджується з App Router і Server Components.
Tailwind v4 позбувся застарілих конфігурацій і працює за принципом zero-config
by default.
- Встановлення Tailwind CSS v4
Найпростіший спосіб — під час створення проєкту:
npx create-next-app@latestУ CLI обрати:
Tailwind CSS
Або додати в існуючий проєкт
npm install tailwindcss@latestPostCSS, autoprefixer та додаткові плагіни не потрібні.
- Глобальні стилі (обовʼязково)
У Tailwind CSS v4 не використовуються директиви
@tailwind base / components / utilities.
Єдиний правильний спосіб підключення — через @import.
/* app/globals.css */
@import "tailwindcss";- Підключення глобальних стилів у App Router
// app/layout.tsx
import './globals.css';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}- глобальні стилі імпортуються один раз
- працюють у Server та Client Components
- не потребують
'use client'
- Конфігурація Tailwind (опціонально)
У Tailwind v4 tailwind.config не є обовʼязковим. Він потрібен лише для
кастомізації (теми, кольори, плагіни).
// tailwind.config.ts
import type { Config } from 'tailwindcss';
const config: Config = {
theme: {
extend: {
colors: {
brand: '#000',
},
},
},
};
export default config;Поле content не використовується.
- Використання Tailwind у компонентах
Tailwind-класи можна використовувати:
- у Server Components
- у Client Components
- без додаткових налаштувань
export default function Page() {
return <h1 className="text-2xl font-bold text-center">Hello Tailwind v4</h1>;
}- Поєднання з іншими підходами
Tailwind CSS v4 можна комбінувати з:
- CSS-модулями
- clsx / classnames
- умовною стилізацією
<div className={clsx('p-4', isActive && 'bg-green-500')} />- Використовувати Tailwind як основний спосіб стилізації
- Мінімізувати глобальні стилі
- Не створювати tailwind.config без потреби
- Поєднувати з Server Components для кращої продуктивності
Коротко:
- Tailwind CSS v4 інтегрується через @import "tailwindcss"
- tailwind.config — опціональний, без content
- Повністю сумісний з Next.js 16+ та App Router
- Простий, швидкий і сучасний підхід до стилізації
33. Що таке компонент Image і як він оптимізує продуктивність?
Компонент Image з пакета next/image — це вбудований інструмент
оптимізації зображень у Next.js 16+.
Він автоматично оптимізує завантаження зображень, зменшуючи розмір трафіку,
час першого рендеру та CLS без ручних налаштувань.
- Автоматичний lazy loading
- Зображення завантажуються лише тоді, коли зʼявляються у viewport
- Зменшує initial load та TTI
- Увімкнений за замовчуванням
import Image from 'next/image';
<Image src="/hero.png" alt="Hero" width={600} height={400} />;- Адаптивні розміри (responsive images)
- Next.js генерує кілька версій зображення
- Браузер отримує оптимальний розмір під конкретний екран
- Менше байтів → швидше завантаження
- Сучасні формати зображень
- Автоматично використовує WebP / AVIF, якщо підтримуються браузером
- Не потребує ручної конвертації
- Запобігання layout shift (CLS)
widthіheightрезервують місце в layout- Сторінка не «стрибає» під час завантаження
<Image src="/photo.jpg" alt="Photo" width={300} height={200} />- Оптимізація на сервері
- Зображення оптимізуються на сервері або edge
- Кешуються та повторно використовуються
- Працює з локальними та віддаленими зображеннями
- Пріоритетне завантаження (priority)
Для hero-зображень можна вимкнути lazy loading:
<Image src="/hero.png" alt="Hero" width={800} height={500} priority />- Використовувати
Imageзамість<img>для контентних зображень - Завжди вказувати
widthтаheight priority— лише для above-the-fold- Для іконок/декору можна використовувати
<img>або SVG
Коротко:
Image— вбудований оптимізатор зображень у Next.js- Забезпечує lazy loading, responsive sizes та modern formats
- Зменшує CLS і покращує initial load
- Рекомендований для більшості зображень у Next.js 16+
34. Як Next.js працює з шрифтами?
У Next.js робота зі шрифтами реалізована через вбудований модуль
next/font, який забезпечує автоматичну оптимізацію шрифтів без ручних
<link> або сторонніх CDN.
Це зменшує CLS, прискорює initial load та покращує Core Web Vitals.
next/font дозволяє:
- self-host-ити шрифти
- автоматично preload-ити потрібні файли
- уникати FOIT/FOUT
- мінімізувати CLS
Працює за замовчуванням з App Router та Server Components.
- Google Fonts через
next/font/google
// app/fonts.ts
import { Inter } from 'next/font/google';
export const inter = Inter({
subsets: ['latin'],
display: 'swap',
});Використання в layout:
// app/layout.tsx
import { inter } from './fonts';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en" className={inter.className}>
<body>{children}</body>
</html>
);
}- Локальні шрифти через
next/font/local
import localFont from 'next/font/local';
export const myFont = localFont({
src: './MyFont.woff2',
display: 'swap',
});- шрифти зберігаються у проєкті
- повний контроль над файлами
- ідеально для кастомних брендових шрифтів
- Оптимізації з коробки
next/font автоматично:
- підвантажує лише потрібні glyph-и
- додає
preload - генерує fallback
- усуває layout shift
Не потрібно:
<link rel="preconnect"><link rel="stylesheet">- сторонні CDN для шрифтів
- Використовувати тільки
next/font - Підключати шрифти у
layout.tsx - Обмежувати кількість font-weights
- Уникати ручних
<link>до шрифтів
Коротко:
- Next.js використовує
next/fontдля шрифтів - Шрифти self-host-яться та preload-яться автоматично
- Значно зменшується CLS і initial load
- Це стандарт і best practice для App Router
35. Як уникнути зайвого JavaScript у клієнтському бандлі?
У Next.js мінімізація клієнтського JavaScript — ключова перевага
фреймворку.
Це досягається завдяки Server Components за замовчуванням, автоматичному
code splitting та чіткому розділенню server/client логіки.
- Використовувати Server Components за замовчуванням
Усі компоненти в App Router є Server Components, якщо явно не вказано інакше.
export default async function Page() {
const data = await getData();
return <div>{data.title}</div>;
}- не потрапляють у JS-бандл
- виконуються на сервері
- можуть робити data fetching напряму
- Мінімізувати використання
'use client'
Директива 'use client':
- переводить компонент у Client Component
- тягне за собою весь dependency tree
'use client';Правило:
використовувати use client лише для інтерактивності.
- Виносити інтерактивність у дрібні Client Components
Погано:
'use client';
export default function Page() {
// велика сторінка стає клієнтською
}Добре:
export default function Page() {
return (
<>
<StaticContent />
<ClientButton />
</>
);
}// ClientButton.tsx
'use client';
export function ClientButton() {
return <button>Click</button>;
}- Уникати client-side data fetching без потреби
Не рекомендовано для основного контенту:
useEffect(() => {
fetch('/api/data').then(...);
}, []);Краще:
- data fetching у Server Components
- кешування через
fetch+revalidate
- Використовувати dynamic import для важких компонентів
import dynamic from 'next/dynamic';
const Chart = dynamic(() => import('./Chart'), {
ssr: false,
});- код завантажується лише за потреби
- зменшує initial bundle
- Обережно з бібліотеками
- не імпортувати важкі бібліотеки в Client Components
- не використовувати універсальні UI-бібліотеки без аналізу
- віддавати перевагу tree-shakable пакетам
- Використовувати вбудовані можливості Next.js
next/imageзамість<img>next/fontзамість<link>- Server Actions замість client API calls
Це зменшує JS і покращує performance.
Коротко:
- Server Components — основний інструмент зменшення JS
'use client'слід використовувати точково- Інтерактивність виноситься в малі компоненти
- Dynamic imports і server-side data fetching зменшують клієнтський бандл
36. Які переваги деплою Next.js-застосунку на Vercel?
Vercel — це офіційна платформа-хостинг для Next.js, створена тією ж
командою.
Вона забезпечує максимальну сумісність з Next.js, автоматизуючи більшість
продакшен-налаштувань.
- Zero-config деплой
- не потрібні кастомні сервери
- автоматичний білд та деплой
- повна підтримка App Router
git push → build → deploy- Підтримка всіх можливостей Next.js
Vercel з коробки підтримує:
- App Router
- React Server Components
- Server Actions
- Route Handlers
- ISR та on-demand revalidation
- Streaming та partial rendering
Без workaround-ів та кастомних конфігів
- Edge Network та продуктивність
- глобальна CDN
- edge-функції для Middleware
- мінімальний latency
- кращі Core Web Vitals
- Автоматичне масштабування
- serverless / edge execution
- масштабування без ручного керування
- стабільна робота при пікових навантаженнях
- ISR та кешування “як задумано”
- ISR працює нативно
- правильне кешування
fetch - revalidation без додаткових налаштувань
На інших хостингах ISR часто обмежений або нестабільний.
- Preview Deployments
- окремий деплой для кожного PR
- унікальний URL
- зручно для code review та QA
- Інтеграція з GitHub
- автоматичні деплої з
main/develop - статуси білду в PR
- швидкий rollback
- Зручна робота зі змінними середовища
- UI для env variables
- різні env для preview / production
- безпечне зберігання секретів
- сучасні Next.js проєкти
- SEO-критичні застосунки
- стартапи та продакшен MVP
- проєкти з активним ISR та Server Actions
Коротко:
- Vercel — офіційна платформа для Next.js
- Повна підтримка App Router і Server Components
- Zero-config деплой і глобальна CDN
- Найкраща сумісність і продуктивність “з коробки”
37. Як налаштувати власні доменні імена при деплої Next.js-застосунку?
У Next.js налаштування власного домену не залежить від коду, а
виконується на рівні хостинг-платформи.
Найпростіший і рекомендований варіант — деплой на Vercel, де підтримка
кастомних доменів реалізована out of the box.
-
Додавання домену у Vercel
-
Зайти в Vercel Dashboard
-
Обрати потрібний проєкт
-
Перейти в Settings → Domains
-
Додати домен (наприклад
example.com)
Vercel автоматично:
- перевірить конфігурацію
- підкаже потрібні DNS-записи
- Налаштування DNS у доменного провайдера
Залежно від типу домену, Vercel запропонує:
Варіант A — apex-домен (example.com)
Type: A
Name: @
Value: 76.76.21.21Варіант B — піддомен (www.example.com)
Type: CNAME
Name: www
Value: cname.vercel-dns.comDNS-записи додаються у панелі керування доменом, не у Next.js.
- HTTPS і SSL
- Vercel автоматично видає SSL-сертифікат
- HTTPS вмикається без ручних налаштувань
- Сертифікати автоматично оновлюються
Не потрібно налаштовувати Let’s Encrypt вручну.
- Redirect між www / non-www
Рекомендовано мати єдиний канонічний домен.
Через Vercel Domains (рекомендовано)
увімкнути redirect у налаштуваннях домену
Або через Next.js Middleware
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(req: NextRequest) {
const url = req.nextUrl;
if (url.hostname === 'www.example.com') {
url.hostname = 'example.com';
return NextResponse.redirect(url);
}
}- Кілька доменів / середовищ
Vercel підтримує:
example.com— productionpreview.example.com— preview- auto-generated домени для PR
Це не потребує змін у коді Next.js.
- Важливі моменти для Next.js 16+
- App Router не потребує додаткової конфігурації
- routing працює однаково для всіх доменів
- ISR, Server Actions і Middleware працюють без змін
- Використовувати HTTPS завжди
- Налаштувати canonical-домен (www або non-www)
- Не хардкодити домен у коді
- Для env-залежних URL використовувати env variables
Коротко:
- Кастомні домени налаштовуються на рівні хостингу
- На Vercel це робиться через Settings → Domains
- SSL і HTTPS вмикаються автоматично
- Next.js не потребує змін у коді для доменів
38. Поясни, як деплоїти Next.js-застосунок з SSR на Netlify.
Деплой Next.js з SSR на Netlify можливий, але не є нативним, як на
Vercel.
Netlify підтримує Next.js через Netlify Next.js Runtime, який транслює
можливості Next.js у Netlify Functions та Edge Functions.
- Базові вимоги
Для SSR на Netlify потрібно:
- Next.js 13+ / 16+
- App Router
- Node runtime (не static export)
- Пакет
@netlify/plugin-nextjs
output: 'export' НЕ використовується, бо він вимикає SSR.
- Підготовка Next.js-проєкту
next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
};
module.exports = nextConfig;Не використовувати:
output: 'export'- Налаштування Netlify
netlify.toml
[build]
command = "npm run build"
publish = ".next"
[[plugins]]
package = "@netlify/plugin-nextjs"плагін автоматично:
- налаштовує SSR
- підключає Netlify Functions
- обробляє routing
- Як працює SSR на Netlify
- SSR-сторінки → Netlify Serverless Functions
- Middleware → Netlify Edge Functions
- Статичні сторінки → CDN
- ISR → обмежена підтримка
Request
→ CDN
→ Netlify Function (SSR)
→ HTML- Data fetching та SSR
SSR працює коректно з:
await fetch(url, { cache: 'no-store' });Також автоматично SSR:
- при використанні cookies / headers
- при
dynamic = 'force-dynamic'
- Обмеження Netlify (ВАЖЛИВО)
❗ Порівняно з Vercel
| Можливість | Vercel | Netlify |
|---|---|---|
| SSR | ✅ нативно | |
| App Router | ✅ | |
| Server Actions | ❌ / |
❌ |
| ISR | ✅ | |
| Edge Middleware | ✅ |
Server Actions у Netlify не підтримуються повноцінно.
- Коли Netlify — нормальний вибір
- проєкт переважно статичний
- мінімальний SSR
- без Server Actions
- вже існує Netlify-інфраструктура
- Використовувати SSR лише там, де потрібно
- Основний контент — SSG / ISR
- Уникати Server Actions
- Тестувати SSR-флоу окремо
Коротко:
- SSR у Next.js 16+ на Netlify можливий через
@netlify/plugin-nextjs - SSR реалізується через Netlify Functions
- Підтримка App Router — часткова
- Є обмеження щодо ISR та Server Actions
- Vercel залишається більш нативним варіантом для Next.js
39. Яка структура папок рекомендується для великих Next.js-застосунків?
У Next.js рекомендована структура папок базується на App Router,
розділенні відповідальностей та feature-oriented підході.
Мета — зробити код масштабованим, читабельним і зручним для команд з
кількох розробників.
- Базова структура для великого проєкту
app/
├─ (public)/ # публічні маршрути
│ ├─ page.tsx
│ └─ layout.tsx
├─ (auth)/ # route group (не впливає на URL)
│ ├─ login/
│ └─ register/
├─ dashboard/ # feature / domain
│ ├─ page.tsx
│ ├─ layout.tsx
│ └─ loading.tsx
├─ api/ # Route Handlers
│ └─ users/
│ └─ route.ts
├─ layout.tsx # root layout
└─ globals.cssapp/— єдине джерело маршрутів- route groups
(( ))— для логічного групування - кожен feature має власний layout і стани
- Feature-oriented структура (рекомендовано)
Для великих застосунків краще групувати код за фічами, а не за типами файлів.
features/
├─ auth/
│ ├─ components/
│ ├─ actions.ts
│ ├─ services.ts
│ └─ types.ts
├─ dashboard/
│ ├─ components/
│ ├─ queries.ts
│ └─ utils.tsЦе:
- спрощує навігацію в коді
- зменшує coupling
- полегшує рефакторинг
- Загальні папки (shared / core)
components/ # спільні UI-компоненти
lib/ # server-side helpers (db, auth, fetch)
hooks/ # client hooks
styles/ # CSS-модулі / tokens
types/ # глобальні TypeScript типиВажливо:
lib/— тільки серверний кодhooks/— тільки client-sidecomponents/— без бізнес-логіки
- Розділення server / client логіки
Рекомендовано явно відокремлювати:
lib/
├─ db.ts # server-only
├─ auth.ts # server-only
components/
├─ Button.tsx # server або client
└─ Modal.client.tsxАбо через директорії:
server/
client/- Що не рекомендується
- одна велика папка components для всього
- змішувати server і client код без структури
- глибока вкладеність без сенсу
- дублювання логіки між фічами
- Best practices для великих команд
- Використовувати route groups
- Тримати мінімум Client Components
- Feature-based структура
- Єдині правила неймінгу
- Документувати архітектуру в README
Коротко:
- Основа — app/ з App Router
- Feature-oriented структура — найкращий вибір
- Route groups допомагають логічно організувати маршрути
- Чітке розділення server / client коду — must-have
40. Як організувати компоненти для кращої масштабованості?
У Next.js масштабованість компонентів досягається завдяки Server
Components за замовчуванням, feature-oriented підходу та чіткому
розділенню відповідальностей.
Ключова ідея — менше Client Components, більше композиції.
- Використовувати Server Components як стандарт
У App Router всі компоненти є серверними, якщо явно не вказано 'use client'.
export default async function Page() {
const data = await getData();
return <List items={data} />;
}Переваги:
не потрапляють у клієнтський бандл
безпечний доступ до БД/секретів
краща продуктивність
- Виносити інтерактивність у малі Client Components
Погано (великий клієнтський компонент):
'use client';
export default function Page() {
/* багато логіки */
}Добре (точкова інтерактивність):
export default function Page() {
return (
<>
<StaticSection />
<InteractiveToggle />
</>
);
}// InteractiveToggle.tsx
'use client';
export function InteractiveToggle() {
/* мінімум логіки */
}- Feature-oriented структура (рекомендовано)
Групувати компоненти за фічами, а не за типами.
features/
├─ auth/
│ ├─ components/
│ ├─ actions.ts
│ └─ services.ts
├─ dashboard/
│ ├─ components/
│ └─ queries.tsЦе зменшує coupling і спрощує розвиток.
- Розділяти “presentational” та “container” компоненти
Presentational — UI без бізнес-логіки Container — data fetching та orchestration (частіше серверні)
// Container (Server Component)
export default async function UsersSection() {
const users = await getUsers();
return <UsersList users={users} />;
}
// Presentational
export function UsersList({ users }) {
return users.map(u => <div key={u.id}>{u.name}</div>);
}- Уникати “god components”
- Один компонент робить все
- Композиція з дрібних компонентів
<Page>
<Header />
<Filters />
<Table />
<Pagination />
</Page>- Чітко розділяти server / client код
Рекомендації:
- серверна логіка →
lib/,actions.ts,services.ts - клієнтська логіка →
hooks/,.client.tsx - не імпортувати server-код у Client Components
- Стандартизувати неймінг і правила
*.client.tsx— клієнтські компоненти*.server.ts— серверні утиліти- Єдині правила імпортів та структури
- Документувати патерни в README
Коротко:
- Server Components — база для масштабованості
- Client Components — лише для інтерактивності
- Feature-oriented структура спрощує розвиток
- Композиція > великі монолітні компоненти
41. Які best practices з безпеки варто враховувати в Next.js-застосунку?
У Next.js безпека значною мірою базується на Server Components,
ізоляції клієнтського коду та контролі доступу на сервері.
Фреймворк дає сильну основу, але відповідальність за коректне використання — на
розробнику.
- Розділяти server та client код
- Server Components не потрапляють у клієнтський бандл
- Секрети та бізнес-логіка мають залишатися на сервері
// ❌ не використовувати в Client Components
process.env.SECRET_KEY;
// ✅ тільки Server Components / Route Handlers
const secret = process.env.SECRET_KEY;- Правильно використовувати змінні середовища
- не зберігати секрети з
NEXT_PUBLIC_ - використовувати
NEXT_PUBLIC_лише для публічних значень - зберігати секрети тільки на сервері
- Захищати API-роути та Server Actions
- перевіряти автентифікацію
- перевіряти ролі та права доступу
- не довіряти даним з клієнта
if (!user || user.role !== 'admin') {
return new Response('Forbidden', { status: 403 });
}- Використовувати Middleware для pre-request перевірок
Middleware підходить для:
- auth-gate
- редиректів
- захисту приватних маршрутів
export function middleware(req: NextRequest) {
if (!isAuthenticated(req)) {
return NextResponse.redirect(new URL('/login', req.url));
}
}- Захист від XSS
- не використовувати dangerouslySetInnerHTML без санітизації
- довіряти React-escaping за замовчуванням
- санітизувати HTML з CMS
- Захист від CSRF
- використовувати same-site cookies
- перевіряти origin / headers
- для форм — Server Actions замість client fetch
- Валідація вхідних даних
- не довіряти params, searchParams, body
- валідовувати всі дані
- повертати коректні HTTP-статуси
if (!isValid(id)) {
notFound();
}- Обмежувати доступ до cookies та headers
- використовувати httpOnly, secure, sameSite
- не читати cookies у Client Components
- працювати з cookies тільки на сервері
- Мінімізувати attack surface
- мінімум API-ендпоінтів
- мінімум Client Components
- мінімум зовнішніх бібліотек
- видаляти невикористаний код
- Покладатися на платформу (Vercel / Netlify)
- HTTPS за замовчуванням
- захист від DDoS
- ізоляція serverless-функцій
- автоматичні security updates
Коротко:
- Server Components — основа безпеки в Next.js 16+
- Секрети ніколи не потрапляють у клієнт
- API та Server Actions мають бути захищені
- Валідація, auth і мінімізація Client Components — ключові принципи
42. Як Next.js працює з cookies?
У Next.js 16+ робота з cookies відбувається виключно на сервері через
вбудовані API App Router.
Cookies вважаються частиною серверного контексту, тому вони тісно
інтегровані з Server Components, Route Handlers, Server Actions та
Middleware.
- Основний API для роботи з cookies
Next.js надає хелпер cookies() з модуля next/headers.
import { cookies } from 'next/headers';Це стандартний і рекомендований спосіб роботи з cookies у Next.js 16+.
- Читання cookies (Server Components)
import { cookies } from 'next/headers';
export default function Page() {
const cookieStore = cookies();
const theme = cookieStore.get('theme');
return <div>Theme: {theme?.value}</div>;
}- працює лише на сервері
- автоматично робить сторінку динамічною (SSR)
- Запис і видалення cookies (Server Actions / Route Handlers)
Запис cookies
'use server';
import { cookies } from 'next/headers';
export async function setTheme() {
cookies().set('theme', 'dark', {
httpOnly: true,
secure: true,
sameSite: 'lax',
});
}Видалення cookies
cookies().delete('theme');У Server Components cookies можна лише читати, але не змінювати.
- Cookies в API-роутах (Route Handlers)
import { cookies } from 'next/headers';
export async function GET() {
const token = cookies().get('token');
return Response.json({ token: token?.value });
}- Cookies у Middleware
Middleware часто використовується для:
- auth-gate
- редиректів
- перевірки сесій
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(req: NextRequest) {
const token = req.cookies.get('token');
if (!token) {
return NextResponse.redirect(new URL('/login', req.url));
}
}- Cookies і Client Components
Client Components не мають прямого доступу до cookies.
- немає
document.cookie - немає
cookies()
Єдиний варіант:
- передати значення з сервера через props
- або отримати дані через API
- Вплив cookies на рендеринг
Використання cookies:
- автоматично вимикає static rendering
- сторінка стає SSR
- кешування за замовчуванням не застосовується
Це очікувана і коректна поведінка.
- Працювати з cookies тільки на сервері
- Для auth використовувати
httpOnlycookies - Не зберігати чутливі дані у client-accessible cookies
- Не читати cookies в Client Components
- Використовувати Server Actions для мутацій
Коротко:
- Cookies у Next.js — серверна відповідальність
- Читання: Server Components, Route Handlers, Middleware
- Запис: Server Actions або API-роути
- Використання cookies робить сторінку динамічною (SSR)
43. Як Next.js працює з headers?
У Next.js робота з HTTP headers є серверною відповідальністю і
інтегрована в App Router.
Headers доступні у Server Components, Route Handlers, Server Actions
та Middleware, але не доступні напряму в Client Components.
- Читання headers у Server Components
Для читання headers використовується хелпер headers() з next/headers.
import { headers } from 'next/headers';
export default function Page() {
const headersList = headers();
const userAgent = headersList.get('user-agent');
return <div>User-Agent: {userAgent}</div>;
}- працює тільки на сервері
- робить сторінку динамічною (SSR)
- Headers у Route Handlers (API-роутах)
У Route Handlers headers читаються та встановлюються через стандартний Web Fetch API.
export async function GET(request: Request) {
const auth = request.headers.get('authorization');
return new Response(JSON.stringify({ auth }), {
headers: {
'Content-Type': 'application/json',
'X-Custom-Header': 'example',
},
});
}- Headers у Server Actions
Server Actions можуть читати headers, але зазвичай не використовуються для їх зміни напряму — для цього краще підходять Route Handlers або Middleware.
'use server';
import { headers } from 'next/headers';
export async function action() {
const locale = headers().get('accept-language');
return locale;
}- Headers у Middleware
Middleware виконується до рендерингу і ідеально підходить для роботи з headers:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(req: NextRequest) {
const res = NextResponse.next();
res.headers.set('x-app-version', '1.0.0');
return res;
}Типові кейси:
- auth / access control
- redirects
- A/B testing
- geo-based логіка
- security headers
- Вплив headers на рендеринг і кеш
Використання headers:
- вимикає static rendering
- сторінка стає SSR
- сторінка не кешується за замовчуванням
Це очікувана поведінка, оскільки headers залежать від запиту.
- Headers і Client Components
Client Components не мають прямого доступу до headers.
Допустимі варіанти:
- передати значення з сервера через props
- отримати дані через API
- Працювати з headers тільки на сервері
- Використовувати Middleware для pre-request логіки
- Не читати headers без потреби (впливає на SSR)
- Для безпеки налаштовувати headers централізовано
- Не хардкодити логіку на основі
user-agentбез необхідності
Коротко:
- Headers у Next.js доступні лише на сервері
- Читання: Server Components, Route Handlers, Middleware
- Зміна: Route Handlers, Middleware
- Використання headers робить сторінку динамічною (SSR)
44. Як керувати глобальним станом без зовнішніх бібліотек?
У Next.js 16+ (App Router) глобальний стан часто можна організувати без Redux/Zustand через вбудовані інструменти платформи:
- Server Components
- URL state (
searchParams) - cookies
- React Context
- Server Actions
- Server-first підхід
Більшість "глобальних" даних у Next.js мають серверну природу:
- сесія користувача
- роль/permissions
- дані профілю
- фільтри, що впливають на SSR
Такі дані краще читати в Server Components і передавати вниз через props.
- URL як джерело істини
Для стану інтерфейсу (пошук, сортування, фільтри, пагінація) використовуй URL:
- стан зберігається у
searchParams - легко шарити посилання
- працює з back/forward навігацією
Це часто замінює "глобальний store" для сторінок списків.
- Cookies для персистентних налаштувань
Для теми, локалі, user preferences:
- читаємо на сервері через
cookies() - змінюємо через Server Actions або Route Handlers
Так стан узгоджений між SSR і клієнтом.
- React Context для client-only глобального стану
Context достатній для невеликого глобального стану в клієнті:
- active tab
- UI-прапорці (sidebar open/close)
- тимчасові interaction-стани
'use client';
import { createContext, useContext, useState } from 'react';
const UiContext = createContext<{
isSidebarOpen: boolean;
setSidebarOpen: (v: boolean) => void;
} | null>(null);
export function UiProvider({ children }: { children: React.ReactNode }) {
const [isSidebarOpen, setSidebarOpen] = useState(false);
return <UiContext.Provider value={{ isSidebarOpen, setSidebarOpen }}>{children}</UiContext.Provider>;
}
export function useUi() {
const ctx = useContext(UiContext);
if (!ctx) throw new Error('useUi must be used inside UiProvider');
return ctx;
}- Server Actions для мутацій
Замість глобального client-store для синхронізації:
- мутація на сервері через Server Action
- після зміни викликаємо
revalidatePath/revalidateTag
Це дає консистентний стан без дублювання логіки на клієнті.
Подумай про зовнішню state-бібліотеку, якщо:
- великий обсяг client-only стану
- складні залежності між багатьма client-компонентами
- high-frequency updates у браузері (наприклад, редактори/конструктори)
Коротко:
- У Next.js глобальний стан часто закривається без бібліотек: server-first + URL + cookies + Context.
- Server Actions замінюють частину client-side синхронізації стану.
- Зовнішній store підключають лише коли реально домінує складний client-only state.
45. Коли доцільно підключати бібліотеки керування станом?
У Next.js більшість задач керування станом вирішуються через:
- Server Components
- Server Actions
- URL / cookies
- React Context
Зовнішні state-бібліотеки потрібні лише в окремих сценаріях, коли стандартних інструментів недостатньо.
Не використовуй Redux/Zustand, якщо:
- дані приходять із сервера (SSR / SSG / ISR)
- стан можна зберігати в:
- URL (фільтри, пошук, пагінація)
- cookies (auth, preferences)
- мутації виконуються через Server Actions
- стан локальний для одного компонента
У більшості Next.js-проєктів цього достатньо.
- Великий клієнтський застосунок (SPA-like)
Якщо багато:
- client-only логіки
- складної взаємодії між компонентами
- стану, що часто змінюється на клієнті
Приклади:
- конструктори (drag & drop)
- дашборди з real-time UI
- складні форми / multi-step flows
- Глобальний UI-стан, що часто змінюється
Наприклад:
- глобальні модалки
- toast-система
- sidebar / layout state
- client-side кеш
У таких випадках Zustand або Jotai — хороший вибір.
- Real-time дані на клієнті
- WebSocket
- live-оновлення
- streaming UI
- collaborative editing
Server Components тут не підходять.
- Складна взаємозалежна логіка стану
Коли:
- багато взаємоповʼязаних частин стану
- складні transitions
- потрібна централізована логіка
Тоді може знадобитись Redux Toolkit.
Для:
- auth
- основних даних сторінки
- даних із БД
- SEO-критичного контенту
- server-side стану
Це повинно жити на сервері.
State-бібліотеки працюють лише у Client Components:
'use client';Тому:
- вони збільшують JS-бандл
- погіршують initial load
- не повинні використовуватись без необхідності
Коротко:
- У більшості Next.js проєктів state-бібліотеки не потрібні
- Вони виправдані для складного client-side UI або real-time логіки
- Працюють тільки у Client Components
- Підключати їх варто лише при реальній необхідності
46. Яка роль tsconfig.json у Next.js-проєкті?
Файл tsconfig.json визначає, як TypeScript компілює та перевіряє код у
Next.js-проєкті.
У Next.js 16+ цей файл також впливає на:
- типізацію
- alias-імпорти
- перевірку помилок під час build
- роботу редактора (VS Code)
Next.js автоматично створює базову конфігурацію при першому запуску TypeScript.
- Типова конфігурація Next.js
{
"compilerOptions": {
"target": "ESNext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"strict": true,
"noEmit": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}- Основні ролі
tsconfig.json
Type checking
- перевірка типів під час розробки та build
strict: true— рекомендується для production
Alias-імпорти
{
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
}Використання:
import Button from '@/components/Button';Переваги:
- короткі імпорти
- менше
../../../ - зручність у великих проєктах
Контроль компіляції
noEmit: true— Next.js сам керує збіркою- TypeScript використовується тільки для перевірки типів
- Взаємодія з Next.js
Next.js:
- автоматично читає
tsconfig.json - оптимізує збірку через SWC
- показує TypeScript-помилки під час next build
- створює
next-env.d.ts
Якщо є TypeScript-помилки — build може впасти.
- Важливі опції для Next.js 16+
| Опція | Навіщо |
|---|---|
strict |
безпечний код |
moduleResolution: bundler |
коректна робота з App Router |
jsx: preserve |
JSX обробляє Next.js |
incremental |
швидший type-check |
paths |
alias-імпорти |
- Що не потрібно робити
- змінювати
moduleнаcommonjs - вимикати
strictу production - використовувати
emit— Next.js керує збіркою сам
Коротко:
tsconfig.jsonкерує TypeScript-перевіркою та налаштуваннями компіляції- Використовується для alias-імпортів і strict-режиму
- Next.js читає його під час build
- Це ключовий файл для стабільності та масштабованості проєкту
47. Як визначати типи для сторінок у Next.js?
У Next.js (App Router) сторінки є Server Components за замовчуванням, тому їх типізація базується на:
- типах props сторінки
- типах
paramsдля динамічних маршрутів - типах
searchParamsдля query-параметрів
Next.js не використовує спеціальний тип на кшталт NextPage (він був у Pages
Router).
- Базова типізація сторінки
Сторінка — це звичайна функція з типізованими props.
export default function Page() {
return <div>Hello</div>;
}Спеціальні типи не потрібні.
- Типізація динамічних параметрів (
params)
Для маршруту:
app/posts/[id]/page.tsxtype PageProps = {
params: {
id: string;
};
};
export default function Page({ params }: PageProps) {
return <div>Post: {params.id}</div>;
}app/users/[userId]/posts/[postId]/page.tsxtype PageProps = {
params: {
userId: string;
postId: string;
};
};- Типізація
searchParams
type PageProps = {
searchParams: {
page?: string;
sort?: string;
};
};
export default function Page({ searchParams }: PageProps) {
const page = Number(searchParams.page ?? 1);
return <div>Page: {page}</div>;
}- Комбінована типізація
type PageProps = {
params: { id: string };
searchParams: { tab?: string };
};
export default function Page({ params, searchParams }: PageProps) {
return (
<div>
{params.id} - {searchParams.tab}
</div>
);
}- Типізація для async Server Pages
Сторінки можуть бути async:
type PageProps = {
params: { id: string };
};
export default async function Page({ params }: PageProps) {
const data = await getPost(params.id);
return <div>{data.title}</div>;
}- Типізація
generateStaticParams
export async function generateStaticParams(): Promise<
{ id: string }[]
> {
return [{ id: '1' }, { id: '2' }];
}- Чого не використовують у Next.js 16+
NextPageGetServerSidePropsGetStaticProps- Pages Router типи
- Описувати окремий тип
PageProps - Завжди типізувати
paramsдля динамічних маршрутів - Використовувати optional-поля для
searchParams - Не використовувати legacy типи з Pages Router
Коротко:
- Сторінки в App Router — звичайні функції
- Типізуються через
paramsіsearchParams - NextPage та інші Pages Router типи не використовуються
- Типізація виконується вручну через PageProps
48. Як мігрувати Next.js-проєкт на TypeScript?
У Next.js 16+ перехід на TypeScript максимально спрощений — фреймворк
автоматично налаштовує більшість конфігурації.
Міграція може виконуватись поступово, без повного переписування проєкту.
- Встановлення TypeScript
Встановіть необхідні пакети:
npm install --save-dev typescript @types/react @types/node- Створення першого TypeScript-файлу
Створіть або перейменуйте будь-який файл:
page.js → page.tsxПісля запуску:
npm run devNext.js автоматично:
- створить
tsconfig.json - створить
next-env.d.ts - налаштує рекомендовані опції
- Поступова міграція (рекомендовано)
Next.js підтримує змішаний код:
"allowJs": trueСтратегія:
- Почати з нових файлів (
.ts / .tsx) - Поступово перейменовувати старі
- Типізувати ключові частини:
- компоненти
- API
- утиліти
- data fetching
- Типізація компонентів
type Props = {
title: string;
};
export function Header({ title }: Props) {
return <h1>{title}</h1>;
}- Типізація сторінок (App Router)
type PageProps = {
params: { id: string };
};
export default function Page({ params }: PageProps) {
return <div>{params.id}</div>;
}- Перевірка типів
Next.js перевіряє типи під час build:
npm run buildЯкщо є помилки TypeScript — збірка завершиться з помилкою.
- Важливі налаштування
tsconfig.json
Рекомендовано:
{
"compilerOptions": {
"strict": true,
"noEmit": true,
"moduleResolution": "bundler",
"incremental": true
}
}-
Типова стратегія міграції для великих проєктів
-
Увімкнути TypeScript
-
Залишити
allowJs: true -
Мігрувати:
lib/components/features/
- В кінці вимкнути allowJs
- переписувати весь проєкт одразу
- вимикати
strict - використовувати
anyбез потреби - створювати власний tsconfig з нуля (Next.js генерує оптимальний)
Коротко:
- Встановити TypeScript і створити
.tsабо.tsx - Next.js автоматично створює конфігурацію
- Міграцію можна виконувати поступово
- Рекомендовано використовувати
strictрежим
49. Як TypeScript використовується в API-роутах Next.js?
У Next.js API-роути реалізуються через Route Handlers
(app/api/**/route.ts) і працюють на базі Web Fetch API.
TypeScript використовується для типізації:
- тіла запиту
- відповіді
- параметрів маршруту (
params) - query-параметрів
- Базовий API-роут з TypeScript
// app/api/posts/route.ts
export async function GET(): Promise<Response> {
return Response.json({ posts: [] });
}Next.js автоматично визначає типи, але явне повернення Promise<Response> —
good practice.
- Типізація тіла запиту (POST)
type CreatePostBody = {
title: string;
content: string;
};
export async function POST(request: Request) {
const body: CreatePostBody = await request.json();
return Response.json({
success: true,
title: body.title,
});
}Важливо: request.json() повертає any, тому тип потрібно вказувати вручну.
- Типізація параметрів маршруту (params)
Для маршруту:
app/api/posts/[id]/route.tstype RouteParams = {
params: {
id: string;
};
};
export async function GET(
request: Request,
{ params }: RouteParams
) {
return Response.json({ id: params.id });
}- Типізація query parameters
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const page = Number(searchParams.get('page') ?? 1);
return Response.json({ page });
}Для складних кейсів можна створити тип:
type Query = {
page?: string;
limit?: string;
};- Типізація відповіді
type PostResponse = {
id: string;
title: string;
};
export async function GET(): Promise<Response> {
const data: PostResponse = {
id: '1',
title: 'Hello',
};
return Response.json(data);
}- Використання утиліт для типів
Рекомендовано виносити типи:
types/
└─ api.tsexport type CreateUserBody = {
email: string;
password: string;
};- Що не використовується в Next.js 16+
NextApiRequestNextApiResponsepages/api- Express-подібні типи
App Router використовує стандартні:
RequestResponse
- Завжди типізувати
request.json() - Виносити типи у
types/ - Типізувати
paramsдля динамічних маршрутів - Не використовувати legacy типи з Pages Router
Коротко:
- API-роути в App Router використовують стандартні
RequestіResponse - TypeScript типізує body, params і відповіді
- Legacy типи Pages Router не використовуються
- Типи краще виносити в окремі файли
50. Як забезпечити type safety у Next.js-проєкті?
У Next.js type safety досягається через поєднання:
- суворої конфігурації TypeScript
- типізації серверної та клієнтської логіки
- єдиних типів для API і даних
- перевірки типів під час build
Мета — type-safe потік даних від БД → сервер → UI.
- Увімкнути strict-режим
У tsconfig.json:
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true
}
}Це основа type safety.
- Типізувати сторінки та маршрути
type PageProps = {
params: { id: string };
searchParams: { page?: string };
};
export default function Page({ params }: PageProps) {
return <div>{params.id}</div>;
}- Типізувати data fetching
type Post = {
id: string;
title: string;
};
async function getPost(id: string): Promise<Post> {
const res = await fetch(`/api/posts/${id}`);
return res.json();
}Ніколи не залишати any.
- Спільні типи для клієнта і сервера
types/
└─ post.tsexport type Post = {
id: string;
title: string;
};Використовувати:
- у Route Handlers
- у Server Components
- у Client Components
- Типізація API-роутів
type CreatePostBody = {
title: string;
};
export async function POST(request: Request) {
const body: CreatePostBody = await request.json();
return Response.json(body);
}- Runtime-валидація (важливо)
TypeScript перевіряє на етапі компіляції, але не в runtime. Для повної безпеки використовують схеми (наприклад, Zod).
import { z } from 'zod';
const schema = z.object({
title: z.string(),
});
const body = schema.parse(await request.json());- Типізація Server Actions
'use server';
type FormDataType = {
email: string;
};
export async function submit(data: FormDataType) {
// type-safe
}- Уникати
any
Якщо потрібно тимчасово:
unknown // краще ніж any- Типізувати env-змінні
Створити:
env.d.ts
declare namespace NodeJS {
interface ProcessEnv {
DATABASE_URL: string;
}
}- Перевірка під час build
Next.js запускає type-check під час:
npm run build
Якщо є помилки — build падає.
- Server Components як джерело істини
- Спільні типи (
types/) - Runtime-валидація для зовнішніх даних
- Мінімум Client Components
- Відсутність
any
Коротко:
- Увімкнути
strictрежим - Використовувати спільні типи для server/client
- Типізувати API, сторінки та data fetching
- Додати runtime-валидацію для зовнішніх даних
- Не використовувати
any
51. У чому концептуальна різниця між Pages Router та App Router?
Pages Router і App Router — це два різні підходи до побудови застосунку
в Next.js.
Головна різниця — в архітектурній моделі рендерингу, роботи з даними та
розділенні server/client логіки.
У Next.js 16+ основним і рекомендованим є App Router.
- Архітектурна модель
| Pages Router | App Router |
|---|---|
| React SPA + SSR/SSG через функції | Server-first архітектура |
| Більшість логіки на клієнті | Більшість логіки на сервері |
Сторінки в pages/ |
Маршрути в app/ |
- Робота з даними
Pages Router
Використовує спеціальні lifecycle-функції:
getServerSidePropsgetStaticPropsgetInitialProps
export async function getServerSideProps() {}App Router
Data fetching виконується напряму в компоненті:
export default async function Page() {
const data = await fetch(url);
return <div>{data.title}</div>;
}Переваги:
- менше boilerplate
- вбудоване кешування
- ISR через
revalidate
- Server Components (ключова відмінність)
Pages Router
- всі компоненти — Client Components
App Router
- Server Compon`ents за замовчуванням
'use client'лише за потреби
Це дає:
- менший JS-бандл
- кращу продуктивність
- безпечний доступ до БД/секретів
- Layout і вкладеність
Pages Router
- один
_app.tsx - один
_document.tsx
App Router
Підтримує вкладені layout-и:
app/
├─ layout.tsx
├─ dashboard/
│ ├─ layout.tsx
│ └─ page.tsxТакож доступні:
loading.tsxerror.tsxnot-found.tsx
- Нові можливості App Router
- React Server Components
- Streaming
- Server Actions
- Route Handlers (
app/api) - Кешування на рівні
fetch - Route Groups
Ці можливості відсутні або обмежені у Pages Router.
- Порівняння
| Критерій | Pages Router | App Router |
|---|---|---|
| Server Components | ❌ | ✅ |
| Data fetching | lifecycle-функції | fetch у компоненті |
| Layout nesting | ❌ | ✅ |
| Streaming | ❌ | ✅ |
| Server Actions | ❌ | ✅ |
| Статус | Legacy | Standard |
- Коли використовується Pages Router
- legacy-проєкти
- поступова міграція
- старі бібліотеки
Нові проєкти — тільки App Router.
Коротко:
- Pages Router — legacy клієнт-орієнтований підхід
- App Router — server-first архітектура
- Data fetching через
fetchзамість lifecycle-функцій - App Router — стандарт у Next.js 16+
52. Як працює файловий роутинг в App Router?
У Next.js файловий роутинг базується на структурі папки app/.
Кожна папка відповідає URL-сегменту, а спеціальні файли визначають, що саме
рендериться для цього маршруту.
- Базовий принцип
Структура папок = URL.
app/
├─ page.tsx
├─ about/
│ └─ page.tsx
└─ blog/
└─ page.tsxВідповідні маршрути:
/ → app/page.tsx
/about → app/about/page.tsx
/blog → app/blog/page.tsxФайл page.tsx є точкою входу для маршруту.
- Layout-и
Файл layout.tsx створює спільний інтерфейс для сегмента та його вкладених
маршрутів.
app/
├─ layout.tsx
├─ dashboard/
│ ├─ layout.tsx
│ └─ page.tsx- Root layout — для всього застосунку
- Вкладені layout-и — для конкретних секцій
- Layout-и зберігаються між переходами
- Динамічні маршрути
app/posts/[id]/page.tsxURL:
/posts/123Доступ до параметра:
export default function Page({ params }: { params: { id: string } }) {
return <div>{params.id}</div>;
}- Route Groups (логічне групування)
Папки в дужках не впливають на URL:
app/
├─ (auth)/
│ └─ login/page.tsxURL:
/loginВикористовується для:
- розділення layout-ів
- організації коду
- Спеціальні файли App Router
| Файл | Призначення |
|---|---|
page.tsx |
сторінка |
layout.tsx |
layout |
loading.tsx |
стан завантаження |
error.tsx |
обробка помилок |
not-found.tsx |
404 для сегмента |
route.ts |
API (Route Handler) |
- Catch-all маршрути
app/docs/[...slug]/page.tsxURL:
/docs/a/b/cparams.slug; // ['a', 'b', 'c']Optional catch-all:
[[...slug]]- Вкладеність маршрутів
App Router підтримує глибоку вкладеність:
app/
└─ dashboard/
└─ settings/
└─ profile/
└─ page.tsxURL:
/dashboard/settings/profile- Server Components за замовчуванням
- Layout-и зберігають стан між переходами
- Streaming і loading працюють на рівні сегментів
- Роутинг автоматичний — без ручних конфігурацій
Коротко:
- Маршрути формуються структурою папки
app/ page.tsx— сторінка,layout.tsx— спільний UI- Підтримуються динамічні, catch-all і route groups
- App Router забезпечує server-first і сегментну архітектуру
53. Що таке Server Components і навіщо вони потрібні?
Server Components — це компоненти, які виконуються на сервері, а їх результат (HTML + мінімальні дані) передається в браузер.
У Next.js 16+ (App Router) всі компоненти є Server Components за
замовчуванням.
Client Components потрібно явно позначати директивою:
'use client';- Як працюють Server Components
Процес рендерингу:
- Компонент виконується на сервері
- Виконується data fetching (БД, API, файли)
- Формується HTML + спеціальний payload
- У браузер відправляється без JavaScript компонента
export default async function Page() {
const posts = await fetch('https://api.example.com/posts').then(r =>
r.json()
);
return <div>{posts.length}</div>;
}- Головні переваги
Менший JS-бандл
Server Components:
- не потрапляють у клієнтський bundle
- зменшують initial load
Прямий доступ до серверних ресурсів
Можна безпечно використовувати:
- базу даних
- секрети (
process.env) - файлову систему
const data = await db.post.findMany();Краща продуктивність
- менше hydration
- швидший First Load
- менше клієнтської логіки
- Обмеження Server Components
Server Components не можуть:
- використовувати React hooks (
useState,useEffect) - працювати з браузерними API
- обробляти клієнтські події (
onClick)
Для цього потрібен Client Component:
'use client';
export function Button() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}- Комбінування Server і
Client Server Component може рендерити Client Component:
export default function Page() {
return <Counter />; // Client Component
}Це дозволяє:
- мінімізувати клієнтський JS
- ізолювати інтерактивність
- Типові use cases
Server Components:
- сторінки
- layout-и
- data fetching
- SEO-контент
- dashboard дані
Client Components:
- форми
- кнопки
- модалки
- анімації
- Вплив на архітектуру
Next.js 16+ використовує server-first підхід:
- більшість логіки на сервері
- клієнт — тільки для інтерактивності
- менше глобального client-state
Коротко:
- Server Components виконуються на сервері і не потрапляють у JS-бандл
- Вони зменшують розмір клієнтського коду і покращують продуктивність
- За замовчуванням всі компоненти в App Router — серверні
- Client Components використовуються лише для інтерактивності
54. У чому різниця між Server Components та Client Components?
У Next.js (App Router) компоненти поділяються на два типи:
- Server Components — виконуються на сервері (за замовчуванням)
- Client Components — виконуються у браузері (позначаються
'use client')
Головна різниця — де виконується код і чи потрапляє він у клієнтський JavaScript-бандл.
- Server Components
Виконання
- працюють тільки на сервері
- їх JavaScript не відправляється в браузер
export default async function Page() {
const data = await fetch(url).then(r => r.json());
return <div>{data.title}</div>;
}Можливості
- доступ до БД
- доступ до
process.env - робота з cookies / headers
- data fetching
Обмеження
Не можна:
useState,useEffect- обробники подій (
onClick) - браузерні API (
window,localStorage)
- Client Components
Позначаються директивою:
'use client';Виконання
- працюють у браузері
- додаються до JS-бандлу
- проходять hydration
'use client';
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}Використовуються для
- інтерактивності
- форм
- модалок
- анімацій
- browser API
- Основні відмінності
| Критерій | Server Component | Client Component |
|---|---|---|
| Де виконується | Сервер | Браузер |
| Потрапляє в JS-бандл | ❌ | ✅ |
| useState / useEffect | ❌ | ✅ |
| Event handlers | ❌ | ✅ |
| Доступ до БД / секретів | ✅ | ❌ |
| SEO / performance | Вищий | Нижчий |
- Взаємодія між ними
- Server Component може рендерити Client Component
- Client Component не може імпортувати Server Component
export default function Page() {
return <Counter />; // Client Component
}- Архітектурний принцип Next.js 16+
Server-first
- Максимум Server Components
- Client Components — лише там, де потрібна інтерактивність
Коротко:
- Server Components — сервер, без JS у браузері
- Client Components — браузер, для інтерактивності
- App Router працює за принципом server-first
'use client'слід використовувати мінімально
55. Для чого використовується директива "use client"?
У Next.js 16+ (App Router) всі компоненти є Server Components за
замовчуванням. Директива 'use client' використовується, щоб позначити
компонент як Client Component, який виконується у браузері та підтримує
інтерактивність.
- Як використовувати
Директива повинна бути першим рядком у файлі:
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}Після додавання:
- компонент виконується у браузері
- включається в клієнтський JavaScript-бандл
- проходить hydration
- Коли потрібен
'use client'
Використовуй директиву, якщо компонент:
- використовує React hooks (
useState,useEffect,useReducer) - має обробники подій (
onClick,onChange) - працює з browser API (
window,document,localStorage) - містить інтерактивну логіку (форми, модалки, dropdown тощо)
- Коли не потрібен
Не додавай 'use client', якщо компонент:
- просто відображає дані
- виконує data fetching
- працює з БД або
process.env - використовує
cookiesабоheaders - є layout або сторінкою без інтерактивності
Server Components продуктивніші, бо не додають JavaScript у браузер.
- Вплив на бандл
Важливо:
'use client'збільшує розмір клієнтського JS- всі імпорти такого файлу також потрапляють у бандл
- тому директиву слід використовувати мінімально (server-first підхід)
- Взаємодія з Server Components
- Server Component може рендерити Client Component
- Client Component не може імпортувати Server Component
Коротко:
'use client'робить компонент клієнтським (browser execution)- потрібен для hooks, подій і browser API
- збільшує JS-бандл, тому використовувати тільки там, де є інтерактивність
56. Які обмеження мають Server Components?
У Next.js 16+ Server Components працюють тільки на сервері, тому мають чіткі обмеження, пов'язані з відсутністю виконання у браузері.
- Немає React hooks для клієнтського стану та ефектів
Не можна використовувати:
useStateuseEffectuseReduceruseRef(для взаємодії з DOM)
Ці hooks потребують виконання в браузері, тому для них потрібен Client Component
('use client').
- Немає обробників подій
У Server Component не можна вішати клієнтські події:
onClickonChangeonSubmit
Причина: серверний компонент рендерить HTML, але не додає клієнтську інтерактивну логіку.
- Немає доступу до browser API
Недоступні:
windowdocumentlocalStoragesessionStoragenavigator
Ці API існують лише у середовищі браузера.
- Не можна імпортувати Server Component у Client Component
Композиція працює так:
- Server Component може рендерити Client Component
- Client Component не може імпортувати Server Component напряму
Це архітектурне правило межі між серверним і клієнтським деревом.
- Обмеження по сторонніх бібліотеках
Бібліотеки, що залежать від DOM, window або React hooks, не працюють у Server
Components без виділення клієнтського шару.
Практично: інтерактивну частину виносять у невеликий Client Component, а решту залишають server-first.
Коротко:
- Server Components не підтримують hooks стану/ефектів, події та browser API.
- Для інтерактивності використовують Client Components з
'use client'. - Оптимальна стратегія в Next.js 16+: server-first, client only where needed.
57. Як працює layout і чим він відрізняється від page?
У App Router ці файли мають різне призначення:
page.tsx— це контент конкретного маршрутуlayout.tsx— це спільна оболонка (каркас) для сегмента маршруту та його дочірніх сторінок
- Як працює
page.tsx
- відповідає за UI конкретного URL
- є кінцевою точкою маршруту
- рендериться всередині відповідного
layout
Приклад:
app/dashboard/page.tsx->/dashboardapp/dashboard/settings/page.tsx->/dashboard/settings
- Як працює
layout.tsx
- обгортає всі вкладені
page.tsxі дочірні сегменти - приймає
childrenі рендерить спільну структуру (header, sidebar, nav) - зберігається між переходами всередині свого сегмента (не перемонтовується як сторінка)
Типовий приклад:
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<section>
<aside>Sidebar</aside>
<main>{children}</main>
</section>
);
}- Ключові відмінності
-
page.tsx:- відповідає за унікальний контент конкретного маршруту
- без
page.tsxмаршрут не матиме сторінки для рендерингу
-
layout.tsx:- перевикористовується для групи маршрутів у сегменті
- задає спільний каркас і стабільний UI між навігаціями
- Архітектурна практика в Next.js 16+
- у
layoutвиносять те, що має бути спільним між вкладеними сторінками - у
pageлишають тільки контент конкретного route - це зменшує дублювання та спрощує підтримку структури застосунку
Коротко:
page.tsx= конкретна сторінка маршруту.layout.tsx= спільна оболонка для сегмента і його дочірніх маршрутів.- Layout перевикористовується між переходами, page відповідає за унікальний контент URL.
58. Що таке вкладені layouts і як вони використовуються?
У Next.js 16+ (App Router) вкладені layouts (nested layouts) це ієрархія
файлів layout.tsx у різних сегментах app/, де кожен наступний layout
обгортає дочірній маршрут.
Простими словами:
- кореневий
app/layout.tsxобгортає весь застосунок app/dashboard/layout.tsxобгортає тільки/dashboard/*app/dashboard/settings/layout.tsxобгортає тільки/dashboard/settings/*
- Як це працює в дереві маршрутів
При переході на глибокий маршрут Next.js збирає layout-и зверху вниз:
- root layout
- layout сегмента
- вкладений layout
- цільовий
page.tsx
Тобто UI формується шарами, де кожен рівень додає свою спільну оболонку.
- Навіщо використовувати вкладені layouts
- щоб перевикористовувати спільний UI для групи сторінок
- щоб не дублювати header/sidebar/nav у кожному
page.tsx - щоб розділяти зони застосунку (наприклад, публічна частина і dashboard)
- Практичний приклад структури
app/
layout.tsx
page.tsx
dashboard/
layout.tsx
page.tsx
settings/
layout.tsx
page.tsxДля маршруту /dashboard/settings буде застосовано всі три layout-и:
app/layout.tsxapp/dashboard/layout.tsxapp/dashboard/settings/layout.tsx
- Поведінка під час навігації
- layout зберігає стан і не перемонтовується при переході в межах свого сегмента
- змінюється переважно нижчий рівень (дочірній layout або page)
- це покращує UX і зменшує зайві перерендери спільної оболонки
- Best practice для Next.js 16+
- тримати layout-и максимально тонкими та відповідальними за каркас
- бізнес-логіку конкретного маршруту лишати в
page.tsxабо серверних модулях - використовувати вкладення тільки там, де є реальна спільна структура
Коротко:
- Вкладені layouts це ієрархія
layout.tsx, яка шарово обгортає дочірні маршрути. - Вони прибирають дублювання спільного UI і дають чітку структуру App Router.
- Для глибокого route застосовуються всі layout-и від кореня до поточного сегмента.
59. Як працюють route groups і для чого вони потрібні?
У Next.js 16+ (App Router) route groups це папки в дужках, наприклад
(marketing) або (dashboard), які організовують структуру маршрутів, але
не додають сегмент в URL.
- Базовий принцип
- папка
(group)впливає на файлову структуру, але не на шлях у браузері - сторінка
app/(marketing)/about/page.tsxбуде доступна за URL/about - group зручний для розділення зон застосунку без зміни адрес
- Для чого вони потрібні
- логічно розділяти великі частини проєкту (публічна зона, кабінет, адмінка)
- застосовувати різні
layout.tsxдля різних груп сторінок - тримати чисту архітектуру App Router без штучних сегментів у URL
- Типовий приклад
app/
(marketing)/
layout.tsx
page.tsx
about/page.tsx
(dashboard)/
layout.tsx
dashboard/page.tsxРезультат по URL:
app/(marketing)/page.tsx->/app/(marketing)/about/page.tsx->/aboutapp/(dashboard)/dashboard/page.tsx->/dashboard
- Взаємодія з layout
- кожна route group може мати свій
layout.tsx - цей layout застосовується до сторінок тільки всередині своєї групи
- так легко мати різні оболонки (наприклад, landing layout і app layout)
- Важливі зауваження
- route groups не є механізмом безпеки чи доступів, це лише організація маршрутів
- не варто дублювати однакові URL у різних групах без чіткої причини
- використовуй groups для читабельності і масштабованої структури
Коротко:
- Route groups це папки виду
(name), які не потрапляють у URL. - Вони потрібні для архітектури: розділення зон і окремих layout-ів.
- Це інструмент структури App Router, а не механізм авторизації.
60. Як реалізуються паралельні маршрути?
У Next.js 16+ (App Router) паралельні маршрути реалізуються через
іменовані слоти (named slots) з папками @slotName. Це дозволяє рендерити
кілька незалежних гілок UI одночасно в межах одного layout.
- Базова ідея
- звичайний
childrenце основний слот - додаткові слоти задаються папками
@analytics,@team,@feedтощо - layout приймає ці слоти як окремі пропси і рендерить у потрібних зонах
- Приклад структури
app/dashboard/
layout.tsx
@analytics/page.tsx
@team/page.tsx
page.tsx- Приклад layout зі слотами
export default function DashboardLayout({
children,
analytics,
team,
}: {
children: React.ReactNode;
analytics: React.ReactNode;
team: React.ReactNode;
}) {
return (
<main>
<section>{children}</section>
<aside>{analytics}</aside>
<aside>{team}</aside>
</main>
);
}- Для чого це використовують
- складні дашборди з незалежними панелями
- одночасний показ різних частин інтерфейсу в одному URL-контексті
- краща модульність: кожен слот має свій маршрут і власний рендеринг
- Важливі нюанси
- паралельні маршрути це не вкладені URL-сегменти, а механіка композиції UI
- кожен слот можна незалежно завантажувати та обробляти через власні
loading.tsx/error.tsx - підхід добре працює разом із server-first архітектурою App Router
Коротко:
- Паралельні маршрути в Next.js робляться через слоти
@slotName. - Layout рендерить кілька слотів одночасно як окремі пропси.
- Це зручно для дашбордів і складних сторінок з незалежними UI-блоками.
61. Як працює data fetching у серверних компонентах?
У Next.js 16+ (App Router) у Server Components дані отримують прямо під час
рендерингу на сервері через async/await (найчастіше через fetch), без
useEffect і без клієнтського запиту після завантаження сторінки.
- Базовий підхід
Server Component може бути async, і ти читаєш дані напряму:
export default async function Page() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return <PostsList posts={posts} />;
}Це працює на сервері, тому користувач отримує вже зрендерений результат.
- Кешування і режими fetch
У Next.js fetch на сервері має керування кешем:
cache: 'force-cache'-> використовує Data Cachecache: 'no-store'-> завжди запитує свіжі дані на кожен запитnext: { revalidate: 60 }-> ISR-поведінка (перевалідація раз на 60 секунд)
Приклади:
await fetch(url, { cache: 'force-cache' });
await fetch(url, { cache: 'no-store' });
await fetch(url, { next: { revalidate: 60 } });- Що це дає в реальних задачах
- швидший first load (дані вже в HTML/Server Render output)
- кращий SEO для контентних сторінок
- менше клієнтського JS, бо не потрібен клієнтський fetch для базового рендеру
- Повторні запити і ефективність
Next.js дедуплікує однакові fetch під час одного рендер-проходу, тому однакові
виклики не мають зайво дублювати мережеві запити в межах запиту.
- Оновлення даних
Окрім revalidate у fetch, для on-demand сценаріїв використовують:
revalidatePath()revalidateTag()
Це дозволяє скидати кеш після змін у БД або CMS.
- Практичний підхід для співбесіди
- за замовчуванням: Server Components + server-first data fetching
no-storeдля завжди динамічних данихrevalidate/теги для контрольованого кешу і балансу між свіжістю та швидкістю
Коротко:
- У Server Components дані отримують напряму на сервері через
async/await. - Керування свіжістю робиться через
cache,revalidate,revalidatePath,revalidateTag. - Це дає кращий SEO, менше клієнтського JS і кращу продуктивність App Router.
62. Як Next.js кешує запити fetch?
У Next.js 16+ (App Router) серверний fetch має вбудоване кешування через
Data Cache. За замовчуванням Next.js намагається повторно використати
результат запиту (залежно від конфігурації cache, revalidate, динаміки
маршруту).
- Базова логіка кешування
- Next.js кешує результат
fetchна сервері, щоб не робити зайві запити - кешований результат може використовуватись між запитами користувачів
- це зменшує latency і навантаження на API
- Основні режими
cache: 'force-cache'-> явно кешує результат у Data Cachecache: 'no-store'-> не кешує, завжди бере свіжі даніnext: { revalidate: N }-> кешує і перевалідує черезNсекунд
Приклад:
await fetch(url, { cache: 'force-cache' });
await fetch(url, { cache: 'no-store' });
await fetch(url, { next: { revalidate: 120 } });- Дедуплікація запитів
У межах одного рендеру Next.js дедуплікує однакові fetch, щоб не виконувати
той самий HTTP-запит кілька разів.
- Коли кеш скидається або оновлюється
- автоматично після часу
revalidate - вручну через
revalidatePath() - вручну через
revalidateTag()(якщо запит тегований)
- Практика для App Router
- статичні/рідко змінні дані:
force-cacheабоrevalidate - часто змінні дані (дашборд, live-статуси):
no-store - після мутацій через Server Actions часто роблять on-demand revalidation
Коротко:
- Next.js кешує серверні
fetchу Data Cache для швидшого рендеру. - Кеш контролюється через
cache,next.revalidate,revalidatePath,revalidateTag. - Для динамічних даних використовують
no-store, для решти кеш + перевалідацію.
63. У чому різниця між force-cache та no-store?
У Next.js 16+ (App Router) force-cache і no-store це два протилежні
режими кешування для серверного fetch.
force-cache
- Next.js зберігає результат у Data Cache
- наступні запити можуть отримувати кешовану відповідь
- підходить для даних, які оновлюються рідко
Типові кейси:
- маркетингові сторінки
- довідкові дані
- публічний контент без частих змін
no-store
- результат
fetchне кешується - на кожен HTTP-запит виконується новий запит до джерела даних
- підходить для дуже динамічних даних
Типові кейси:
- live-статуси
- персоналізовані дашборди
- адмін-панелі зі свіжими даними
- Приклад
await fetch(url, { cache: 'force-cache' });
await fetch(url, { cache: 'no-store' });- Практичний вибір
- якщо пріоритет швидкість і можна показати не найсвіжіші дані ->
force-cache - якщо пріоритет абсолютна актуальність на кожен запит ->
no-store - проміжний варіант:
next: { revalidate: N }
Коротко:
force-cacheкешує і пришвидшує рендер.no-storeзавжди тягне свіжі дані, але дорожчий по latency.- Вибір залежить від компромісу між швидкістю та актуальністю.
64. Як працює revalidation даних?
У Next.js 16+ revalidation це механізм оновлення кешованих даних після певного часу або за подією, щоб поєднати швидкість кешу і актуальність контенту.
- Time-based revalidation
Для fetch задають інтервал у секундах:
await fetch(url, { next: { revalidate: 60 } });Що це означає:
- дані кешуються
- протягом 60 секунд повертається кеш
- після вікна revalidate Next.js оновлює кеш новими даними
- On-demand revalidation
Кеш можна скинути вручну після мутації даних:
revalidatePath('/posts')revalidateTag('posts')
Це типово роблять після Server Actions або змін у CMS/БД.
- Коли використовувати
revalidate: Nдля контенту, що оновлюється періодичноrevalidatePathколи зміни торкаються конкретного маршрутуrevalidateTagколи потрібно інвалідовувати групу запитів за тегом
- Що важливо на співбесіді
- revalidation не дорівнює
no-store - це кероване кешування, а не повна відмова від кешу
- дозволяє отримати кращий баланс продуктивності та свіжості даних
Коротко:
- Revalidation оновлює Data Cache за часом або вручну.
- Основні інструменти:
next.revalidate,revalidatePath,revalidateTag. - Це головний механізм "швидко + достатньо свіжо" в App Router.
65. Як реалізується streaming rendering?
У Next.js 16+ (App Router) streaming rendering дозволяє відправляти HTML частинами: користувач бачить готові частини сторінки раніше, поки повільні сегменти ще догружаються.
- Як це працює
- сервер починає рендер одразу
- готові сегменти UI відправляються в браузер по мірі готовності
- повільні ділянки рендеряться пізніше без блокування всього екрану
- Роль
loading.tsx
Для сегмента маршруту можна додати loading.tsx:
- він показується миттєво як fallback
- коли дані готові, Next.js підміняє fallback на реальний контент
- Переваги
- менший TTFB/краще сприйняття швидкості
- користувач раніше бачить каркас сторінки
- повільний запит у частині UI не блокує весь route
- Де це особливо корисно
- дашборди з кількома незалежними віджетами
- сторінки з важкими блоками (аналітика, таблиці, графіки)
- маршрути з різними джерелами даних
- Практика для App Router
- розбивати сторінку на логічні сегменти
- використовувати
loading.tsxна рівні потрібного сегмента - комбінувати зі Server Components і кешуванням для стабільної продуктивності
Коротко:
- Streaming віддає HTML по частинах, а не чекає повного рендеру.
loading.tsxпоказує fallback, поки сегмент догружається.- Це покращує perceived performance, особливо на складних сторінках.
66. Для чого використовується Suspense у Next.js?
У Next.js 16+ (App Router) Suspense використовується для поступового
рендеру UI: поки частина дерева чекає дані або lazy-компонент, користувач бачить
fallback, а не порожню сторінку.
- Основна роль
- ізолює повільний фрагмент інтерфейсу
- показує fallback (
loading state) локально - не блокує рендер усієї сторінки
- Де найчастіше застосовується
- навколо повільних Server Components
- для розділення важких блоків дашборду
- у комбінації з streaming rendering
- Практичний ефект
- кращий perceived performance
- швидший показ ключового контенту
- плавніша поведінка при повільних джерелах даних
Коротко:
Suspenseдозволяє рендерити UI частинами через fallback.- Повільні сегменти не блокують весь екран.
- У Next.js це ключовий інструмент для streaming UX.
67. Як Next.js обробляє loading-стани сторінок?
У App Router loading-стани обробляються через спеціальний файл
loading.tsx на рівні сегмента маршруту.
- Як це працює
- Next.js автоматично показує
loading.tsx, поки сегмент рендериться - коли дані/компонент готові, fallback замінюється реальним UI
- працює разом зі streaming, тому сторінка може відкриватися по частинах
- Рівні застосування
app/loading.tsx-> глобальний loading для кореняapp/dashboard/loading.tsx-> loading тільки для/dashboard/*- вкладені сегменти можуть мати власні loading-екрани
- Best practice
- робити lightweight skeleton замість спінера на весь екран
- ставити loading на потрібному рівні сегмента, не занадто високо
- зберігати стабільний layout, щоб уникати “стрибків” UI
Коротко:
- Loading-стани в App Router задаються через
loading.tsx. - Вони спрацьовують автоматично на рівні відповідного сегмента.
- Найкраще працюють як локальні skeleton-и у streaming-потоці.
68. Як працює error.tsx у App Router?
error.tsx у Next.js 16+ це локальна error boundary для сегмента маршруту.
Вона перехоплює помилки рендерингу/виконання в межах сегмента і показує fallback
UI замість падіння всього застосунку.
- Поведінка
- файл
error.tsxпрацює для свого сегмента і дочірніх сегментів - якщо в сегменті стається помилка, рендериться
error.tsx - решта незачеплених частин дерева може залишатися робочою
- Що отримує компонент
Типово компонент приймає:
error(об'єкт помилки)reset()для повторної спроби рендеру
- Практика
- показувати зрозуміле повідомлення + кнопку retry (
reset) - не виводити технічні stack traces користувачу
- логувати помилки в monitoring (Sentry тощо)
Коротко:
error.tsxце сегментна error boundary в App Router.- Вона ізолює помилки й не дає “впасти” всій сторінці.
- Через
reset()можна зробити retry без повного перезавантаження.
69. Як реалізується сторінка not-found?
У App Router сторінка 404 реалізується через файл not-found.tsx і виклик
notFound() у серверній логіці.
- Базовий механізм
- створюєш
not-found.tsxу потрібному сегменті - у
page.tsx/Server Component викликаєшnotFound(), якщо сутність не знайдена - Next.js рендерить відповідний not-found UI
- Рівні
app/not-found.tsx-> глобальний 404app/blog/not-found.tsx-> локальний 404 для/blog/*
- Коли викликати
notFound()
- запис у БД відсутній
- slug невалідний
- ресурс недоступний для рендеру як сторінка
Коротко:
- 404 в App Router =
not-found.tsx+notFound(). - Можна мати глобальний і сегментні варіанти not-found.
- Це стандартний спосіб обробки "ресурс не знайдено" в Next.js.
70. Як обробляються помилки під час серверного рендерингу?
У Next.js 16+ під час SSR/Server Components помилки обробляються рівнями:
локально через error.tsx, глобально через кореневі boundaries та технічний
логінг на сервері.
- Локальна ізоляція
- помилка в сегменті -> спрацьовує найближчий
error.tsx - інші сегменти маршруту можуть продовжити роботу
- це зменшує blast radius помилки
- Типові джерела помилок
- падіння зовнішнього API
- некоректні дані/схема відповіді
- runtime-помилки в серверній логіці
- Практичний підхід
- обгортати зовнішні виклики в валідацію/try-catch
- повертати контрольовані fallback-и
- логувати помилки централізовано (Sentry, APM)
- Для UX
- показувати user-friendly повідомлення
- давати retry, якщо це тимчасова помилка
- не показувати внутрішні деталі сервера
Коротко:
- SSR-помилки в App Router ловляться через сегментні
error.tsx. - Помилки треба ізолювати, логувати й показувати контрольований fallback.
- Головна мета: стабільний UX навіть при збоях бекенду.
71. Що таке Route Handlers і чим вони відрізняються від API Routes?
Route Handlers це серверні endpoint-и в app/**/route.ts, які працюють у
моделі App Router. Вони є сучасною заміною pages/api/* (API Routes).
- Що таке Route Handlers
- файли
route.ts/route.jsуapp-структурі - обробляють HTTP-методи:
GET,POST,PUT,PATCH,DELETEтощо - повертають
Response/NextResponse
- Головна різниця з API Routes
- API Routes: старий підхід у
pages/api(Pages Router) - Route Handlers: новий підхід App Router, краща інтеграція з сучасною серверною архітектурою Next.js
- Чому в Next.js 16+ обирають Route Handlers
- єдина модель разом з App Router
- зручна інтеграція з Server Components, caching, revalidation
- чистіша структура проєкту без міксу старих і нових патернів
Коротко:
- Route Handlers = сучасні API endpoint-и в
app/**/route.ts. - API Routes (
pages/api) це legacy-підхід для Pages Router. - У Next.js 16+ для нових проєктів використовують Route Handlers.
72. Як реалізувати backend-proxy через Route Handlers?
Backend-proxy через Route Handler це endpoint у Next.js, який приймає запит від клієнта і пересилає його у зовнішній/внутрішній backend, додаючи контроль безпеки, headers, токени і валідацію.
- Навіщо це робити
- приховати приватні URL і ключі
- централізувати auth/header policy
- зняти CORS-проблеми для клієнта
- Базовий приклад
// app/api/proxy/users/route.ts
import { NextResponse } from 'next/server';
export async function GET() {
const res = await fetch(`${process.env.API_URL}/users`, {
headers: { Authorization: `Bearer ${process.env.API_TOKEN}` },
cache: 'no-store',
});
if (!res.ok) {
return NextResponse.json({ message: 'Upstream error' }, { status: res.status });
}
const data = await res.json();
return NextResponse.json(data);
}- Best practice
- whitelist дозволених маршрутів
- валідація input і нормалізація помилок
- таймаути/retry для нестабільних upstream-сервісів
Коротко:
- Route Handler може виступати проксі-шаром між frontend і backend.
- Це дає контроль безпеки, стабільні контракти і простіший клієнт.
- Ключі/секрети лишаються на сервері Next.js.
73. Як Next.js використовується як BFF (Backend for Frontend)?
BFF у Next.js це серверний шар, який адаптує дані і бізнес-операції під потреби конкретного frontend. У Next.js 16+ це зазвичай реалізують через Route Handlers + Server Actions + Server Components.
- Що робить BFF-шар
- агрегує дані з кількох сервісів в один frontend-friendly payload
- інкапсулює авторизацію, ролі, permission checks
- приховує складність backend-сервісів від UI
- Чим це корисно
- тонший клієнтський код
- менше дублювання запитів у різних компонентах
- єдина точка контролю контрактів даних
- Типова схема
- UI -> Next.js (BFF) -> зовнішні API/мікросервіси
- BFF повертає вже нормалізовану відповідь під потребу конкретного екрана
- Практика
- виносити інтеграції у server-only модулі
- тримати policy/security у BFF, не в клієнті
- контролювати кеш і revalidation на серверному шарі
Коротко:
- BFF у Next.js це серверний адаптер між UI і backend-сервісами.
- Він централізує auth, агрегацію даних і бізнес-правила для frontend.
- У App Router його будують на Route Handlers, Server Actions і Server Components.
74. Як проксувати запити до зовнішніх API через Next.js?
Найчастіше проксування роблять через Route Handlers: клієнт звертається до
/api/* у Next.js, а Next.js вже викликає зовнішній API.
- Базовий флоу
- Client ->
/api/external/...(Next.js) - Route Handler додає auth headers/secret/token
- Next.js -> External API
- повернення нормалізованої відповіді клієнту
- Що обов'язково додати
- обробку помилок upstream API
- timeout і fallback-поведінку
- контроль кешу (
force-cache/no-store/revalidate) за типом даних
- Переваги
- секрети не потрапляють у браузер
- стабільний API-контракт для фронтенду
- простіший контроль логування, rate limiting, audit
Коротко:
- Проксі до зовнішніх API в Next.js роблять через Route Handlers.
- Клієнт працює тільки з внутрішнім
/api, без прямих секретних інтеграцій. - Це безпечніше і зручніше для централізації server-logic.
75. Як централізувати авторизацію на рівні server-logic?
У Next.js 16+ централізація авторизації робиться на серверному рівні: Middleware + server-only auth utilities + перевірки у Route Handlers/Server Actions/Server Components.
- Базова стратегія
- Middleware: первинний gate (наприклад, редірект на login)
- server auth helper: єдина функція читання сесії/токена/ролей
- серверні entry points (Route Handlers, Actions, RSC): обов'язковий permission-check перед бізнес-логікою
- Що це дає
- однакові правила доступу в усьому застосунку
- мінімум дублювання перевірок по файлах
- відсутність довіри до клієнта для security-рішень
- Практичні правила
- не перевіряти доступ лише на клієнті
- тримати RBAC/ABAC перевірки в server-only модулях
- повертати стандартизовані
401/403і логувати security-події
- Типова архітектура
middleware.ts-> coarse-grained доступlib/auth/server.ts->getSession(),requireRole()- виклик
requireRole()у кожному чутливому server endpoint
Коротко:
- Авторизацію централізують у server-logic, не в клієнтських компонентах.
- Middleware + спільні auth-утиліти + перевірки в Route Handlers/Actions.
- Це дає передбачувану безпеку і керований доступ у всьому App Router.
76. Як працює edge-logic у Next.js?
Edge-logic у Next.js 16+ це виконання коду ближче до користувача в Edge Runtime (не в повноцінному Node.js-середовищі).
- Де використовується
middleware.ts- Route Handlers з edge runtime
- окремі серверні сценарії, де критична мінімальна затримка
- Що дає
- меншу latency для глобальної аудиторії
- швидші redirect/rewrite/auth checks
- ранню обробку запиту до потрапляння в основний рендер
- Обмеження
- не всі Node API доступні
- треба орієнтуватись на Web APIs та edge-сумісні бібліотеки
Коротко:
- Edge-logic виконує серверний код географічно ближче до юзера.
- Найчастіше використовується в middleware і edge Route Handlers.
- Дає швидкість, але з обмеженнями runtime.
77. У яких випадках доцільно виконувати логіку на edge-рівні?
Edge-рівень доцільний там, де важлива миттєва реакція на запит до рендеру сторінки.
- Типові кейси
- auth/session gate у middleware
- гео/locale redirects
- A/B routing та feature flags
- bot/filter/security checks
- Коли не варто
- важкі обчислення
- код, що залежить від Node-only пакетів
- складна бізнес-логіка з довгими I/O операціями
- Правило вибору
- edge для lightweight pre-processing
- основна бізнес-логіка лишається в server runtime
Коротко:
- Edge доречний для швидких перевірок і маршрутизаційних рішень.
- Не підходить для heavy backend-обробки.
- Хороший pattern: edge gate + server core logic.
78. Як реалізувати захищені серверні маршрути?
У Next.js 16+ захист серверних маршрутів будують через централізовану auth-перевірку в Route Handlers/Server Actions і (за потреби) middleware як перший бар'єр.
- Базовий підхід
- витягнути сесію/токен на сервері
- перевірити роль/permission
- повернути
401або403, якщо доступу немає
- Де перевіряти
- в
app/api/**/route.ts - у Server Actions перед змінами даних
- у Server Components для приватного контенту
- Best practice
- єдиний
requireAuth()/requireRole()helper - жодної довіри до клієнтських перевірок
- audit/log security подій
Коротко:
- Захист роблять на сервері, не на клієнті.
- Route Handlers/Actions мають явний auth + permission check.
- Middleware можна використати як додатковий pre-check.
79. Як працюють Server Actions і яку проблему вони вирішують?
Server Actions це серверні функції, які викликаються напряму з UI (найчастіше з форм), без окремого ручного API-ендпойнта.
- Яку проблему вирішують
- прибирають зайвий boilerplate
form -> client fetch -> API route - зменшують розрив між UI і серверною мутацією
- спрощують обробку форм і side-effects
- Як працюють
- action визначається на сервері
- клієнт/форма викликає її напряму
- код виконується тільки на сервері (з доступом до БД/секретів)
- Де корисні
- CRUD-операції
- submit форм
- дії, що одразу потребують revalidation
Коротко:
- Server Actions це серверні мутації без окремих API-роутів.
- Вони спрощують потік запису даних у App Router.
- Основний плюс: менше коду і краща зв'язка UI + server logic.
80. Як Server Actions можуть замінити API-запити?
Server Actions замінюють API-запити в сценаріях, де клієнту не потрібен універсальний HTTP-контракт, а потрібна пряма серверна дія.
- Було (класично)
- client submit
fetch('/api/...')- API route
- бізнес-логіка
- Стало (Server Actions)
- form/button викликає action
- action одразу робить мутацію на сервері
- за потреби викликає
revalidatePath/revalidateTag
- Коли підходить
- внутрішні форми продукту
- типові create/update/delete дії
- коли важлива простота і контроль server-only логіки
- Коли API лишається доречним
- публічний API для зовнішніх клієнтів
- інтеграції з іншими системами
Коротко:
- Server Actions знімають потребу в багатьох внутрішніх API-запитах.
- Для зовнішнього програмного доступу API-роути все ще потрібні.
- Це про спрощення внутрішніх мутацій у Next.js.
81. Як реалізувати обробку форм без API-роутів?
Форма без API-роутів у Next.js 16+ реалізується через Server Action, прив'язану до action форми.
- Базова схема
- форма відправляє
FormData - Server Action валідовує і зберігає дані
- виконується revalidation/redirect за потреби
- Переваги
- менше boilerplate
- серверна валідація в одному місці
- безпечний доступ до БД і секретів
- Практика
- валідація на сервері обов'язкова
- повертати контрольовані стани помилок
- після успіху оновлювати кеш (
revalidatePath)
Коротко:
- Форми без API-роутів робляться через Server Actions.
- Дані обробляються одразу на сервері через
FormData. - Це коротший і безпечніший шлях для CRUD-форм.
82. Як Next.js працює з cookies у Server Actions?
У Server Actions cookies читаються і записуються на сервері через API cookies, без доступу до document.cookie.
- Що можна робити
- читати значення cookie для сесії/налаштувань
- встановлювати нові cookie (auth/session/flags)
- видаляти cookie при logout
- Чому це важливо
- cookie-операції відбуваються в trusted server контексті
- можна безпечно керувати httpOnly/session даними
- Практичні правила
- чутливі cookie ставити як
httpOnly,secure,sameSite - не тримати секрети в клієнтських cookie без захисту
Коротко:
- У Server Actions cookies керуються серверно.
- Це безпечніше за клієнтський доступ до cookie.
- Для auth-cookie важливі
httpOnlyіsecureпараметри.
83. Як обмежити доступ до серверної логіки?
Доступ до серверної логіки обмежують комбінацією auth, permission checks і server-only модульної архітектури.
- Обов'язкові рівні
- authentication (хто користувач)
- authorization (що йому дозволено)
- resource-level checks (чи має доступ до конкретної сутності)
- Технічна реалізація
requireAuth()/requireRole()у кожному чутливому вході- перевірки в Route Handlers, Server Actions, Server Components
- middleware як ранній gate
- Додатково
- rate limiting
- audit logging
- стандартизовані
401/403
Коротко:
- Обмеження доступу = auth + permission + перевірка ресурсу.
- Перевірки мають бути у всіх серверних entry points.
- Клієнтські перевірки лише UX, не безпека.
84. Як Next.js запобігає витоку серверного коду в клієнт?
Next.js розділяє серверні й клієнтські межі: Server Components не потрапляють у браузерний bundle, а client-code треба явно позначати через 'use client'.
- Механізм
- за замовчуванням App Router-компоненти серверні
- серверні модулі не бандляться в клієнт
- межа контролюється графом імпортів
- Важливі правила
- не імпортувати server-only модулі в Client Components
- secrets тримати лише в серверному коді
- не використовувати
NEXT_PUBLIC_для секретних значень
- Практика
- окремі
serverмодулі для БД/auth/integrations - мінімальний
'use client'footprint
Коротко:
- Server Components не відправляються в клієнтський JS.
- Ризик витоку з'являється при неправильних імпортах і env-практиках.
- Рішення: чітка server/client межа і discipline в структурі коду.
85. Як уникнути hydration mismatch?
Hydration mismatch виникає, коли HTML з сервера не збігається з першим рендером у браузері.
- Типові причини
Math.random(),Date.now()у рендері- різний рендер залежно від
windowна першому проході - неузгоджені локалі/таймзони
- Як уникати
- детермінований рендер на server і client
- browser-only логіку переносити в
useEffect - не змішувати server/client стан без синхронізації
- Практика
- для часових/рандомних значень рендерити стабільний placeholder
- акуратно використовувати умови на клієнтські API
Коротко:
- Mismatch = різний initial UI між сервером і клієнтом.
- Тримай перший рендер детермінованим.
- Browser-only обчислення запускай після hydration.
86. Що таке hydration і як вона працює?
Hydration це процес, коли React у браузері “під'єднує” інтерактивність до вже згенерованого сервером HTML.
- Послідовність
- сервер повертає HTML
- браузер показує контент
- React завантажує JS і прив'язує обробники подій
- Що важливо
- HTML на сервері має збігатися з першим client render
- інакше з'являються hydration warnings/mismatch
- Роль у Next.js
- Server Components мінімізують client JS
- hydration потрібна там, де є Client Components
Коротко:
- Hydration робить серверний HTML інтерактивним.
- Потрібна узгодженість server/client рендеру.
- Чим менше client-частини, тим легша hydration-навантаженість.
87. Як динамічно підвантажувати компоненти?
Динамічне завантаження роблять через next/dynamic, щоб не включати важкі компоненти в initial bundle.
- Базовий приклад
import dynamic from 'next/dynamic';
const HeavyChart = dynamic(() => import('./HeavyChart'), {
loading: () => <p>Loading chart...</p>,
});- Коли використовувати
- важкі віджети (charts/editors/maps)
- компоненти нижче першого екрану
- рідко використані UI-блоки
- Ефект
- менший стартовий JS
- швидший first render
- краща контрольована деградація через loading fallback
Коротко:
next/dynamicвідкладено завантажує компонент.- Це оптимізує bundle і старт сторінки.
- Особливо корисно для heavy клієнтських модулів.
88. Як аналізувати продуктивність Next.js-застосунку?
Продуктивність аналізують у 3 шарах: Web Vitals, bundle size, server/render latency.
- Ключові метрики
- LCP, CLS, INP
- TTFB для серверних маршрутів
- час до інтерактивності критичних екранів
- Що перевіряти технічно
- розмір клієнтських chunk'ів
- надмірний
'use client' - кеш-політики
fetchі revalidation
- Інструменти
- Lighthouse / PageSpeed
- Vercel Analytics / Web Vitals
- APM/Sentry для runtime-помилок і latency
- Стратегія
- server-first архітектура
- локалізація важких клієнтських компонентів
- контроль cache/revalidate по кожному route
Коротко:
- Дивись не лише фронт, а й серверну latency та кеш.
- Найчастіші проблеми: завеликий client bundle і неправильний fetch-cache.
- Регулярний моніторинг важливіший за разову оптимізацію.
89. Як працює metadata API?
Metadata API у App Router дозволяє оголошувати SEO/meta-дані декларативно на рівні layout/page.
- Варіанти
- статично через
export const metadata - динамічно через
generateMetadata
- Що можна задавати
title,description- Open Graph
- Twitter cards
- canonical та інші meta
- Переваги
- централізований SEO-підхід
- краща типобезпека і підтримка
- зручне наслідування metadata через layout tree
Коротко:
- Metadata API це стандартний SEO-механізм App Router.
- Підтримує static і dynamic metadata.
- Працює на рівні маршруту та layout-ієрархії.
90. Як динамічно керувати SEO-метаданими?
Для динамічного SEO використовують generateMetadata, де мета формується на основі params або серверних даних.
- Як працює
- отримуєш
params/searchParams - за потреби фетчиш дані сутності
- повертаєш об'єкт metadata
- Типові сценарії
- сторінка товару/статті з унікальним title/description
- локалізовані метадані
- умовні OG-зображення
- Практика
- fallback metadata на випадок помилок
- не генерувати надто дорогі запити без кеш-стратегії
Коротко:
- Dynamic SEO у Next.js робиться через
generateMetadata. - Metadata формується з route params і серверних даних.
- Важливо мати fallback і контроль fetch-кешу.
91. Як реалізувати Open Graph metadata?
Open Graph задають через Metadata API у полі openGraph (статично або в generateMetadata).
- Що зазвичай вказують
titledescriptionurlsiteNameimagestype
- Практика
- унікальні OG-дані для важливих сторінок
- валідні absolute URL для image
- узгодженість OG title/description з основним SEO
- Чому це важливо
- коректний preview у соцмережах/месенджерах
- кращий CTR при шерінгу
Коротко:
- OG metadata в Next.js налаштовується через
openGraph. - Найкритичніше: коректні title/description та image URL.
- Це напряму впливає на якість link preview.
92. Як Next.js підтримує i18n?
У Next.js i18n зазвичай будують через locale-based routing + словники перекладів на сервері/клієнті.
- Компоненти підходу
- маршрути з locale-сегментом
- middleware для визначення локалі
- словники/ресурси перекладів
- Що отримуємо
- різні URL для мов
- локалізований контент і metadata
- контроль fallback-мови
- Практика
- централізований locale resolver
- однакова структура ключів перекладу
- не змішувати бізнес-дані та i18n-рядки
Коротко:
- i18n в Next.js базується на маршрутизації та locale-aware рендері.
- Ключові частини: routing, middleware, translation dictionaries.
- Важливо синхронізувати i18n і SEO metadata.
93. Як працює locale-based routing?
Locale-based routing це коли мова є частиною URL і визначає, яку локалізовану версію маршруту рендерити.
- Принцип
/en/...,/uk/...тощо- locale витягується з сегмента маршруту
- той самий route рендерить інший контент за поточною локаллю
- Звідки береться locale
- із URL
- з middleware (Accept-Language, cookie, user preference)
- Практичні плюси
- прозорі SEO-friendly адреси
- явна локалізація на рівні навігації
- просте кешування по locale-сегменту
Коротко:
- Locale-based routing робить мову частиною шляху.
- Локаль визначає контент, metadata і навігацію.
- Це стандартна основа багатомовних Next.js-застосунків.
94. Як масштабувати Next.js-застосунок у великій команді?
Масштабування у великій команді це про чіткі архітектурні межі, стандарти server/client коду і прогнозовані процеси релізу.
- Технічна структура
- feature/domain-модулі
- shared UI/infra бібліотеки
- server-only шари для інтеграцій і auth
- Інженерні практики
- обов'язкові code owners + PR checks
- lint/type/test gates у CI
- контрактні правила для API/даних
- Продуктивність і стабільність
- server-first підхід
- контроль
'use client' - route-level performance budgets
Коротко:
- Масштабування = архітектурні межі + процесна дисципліна.
- Треба стандартизувати модульність, тести й релізні gate'и.
- Без цього великий Next.js-кодbase швидко деградує.
95. Як організувати domain-driven структуру проєкту?
Domain-driven структура групує код навколо бізнес-доменів, а не технічних шарів типу “components/hooks/utils” в одному місці.
- Приклад підходу
src/domains/billing/...src/domains/orders/...src/domains/auth/...
- Що всередині домену
- UI для домену
- server actions/handlers
- схеми валідації
- domain services/use-cases
- Переваги
- менша зв'язаність між модулями
- простіше ownership у команді
- швидше вносити зміни в межах домену
Коротко:
- DDD-структура групує код за бізнес-напрямками.
- Кожен домен містить свій UI + server logic + validation.
- Це підвищує масштабованість і командну автономність.
96. Як тестувати Next.js-застосунок?
Тестування будують пірамідою: unit -> integration -> e2e, покриваючи окремо UI, server logic і маршрути.
- Рівні
- unit: утиліти, валідація, domain logic
- integration: компоненти + серверні залежності
- e2e: критичні user flows
- Що покривати пріоритетно
- auth/permissions
- форми і мутації
- критичні маршрути та SEO-сторінки
- Практика
- стабільні тести без крихких snapshot-overuse
- mocks тільки там, де справді потрібно
- окремі smoke e2e на deploy
Коротко:
- Next.js тестують на кількох рівнях, не лише UI-unit.
- Найвищий пріоритет: auth, data mutations, критичні флоу.
- Регресії краще ловляться комбінацією integration + e2e.
97. Як тестувати серверну логіку та Route Handlers?
Серверну логіку і Route Handlers тестують із фокусом на контракти: статуси, валідацію, помилки, авторизацію.
- Що перевіряти
- коректні
200/201/400/401/403/500 - перевірки ролей/доступів
- поведінку при збоях upstream API/БД
- Підхід
- unit для чистих server functions
- integration для handler + залежності
- мінімальні e2e для критичних endpoint-флоу
- Best practice
- ізолювати бізнес-логіку від transport-шару
- тестувати нормалізацію помилок
- перевіряти edge cases валідації input
Коротко:
- Route Handlers тестують як HTTP-контракт + security-поведінку.
- Бізнес-логіку краще виносити окремо й тестувати unit/integration.
- Критично перевіряти error-path, не лише happy-path.
98. Як працюють preview deployments?
Preview deployments це тимчасові оточення для кожного PR/гілки, де команда бачить реальну версію змін до merge у production.
- Навіщо
- швидкий review функціоналу і UI
- перевірка інтеграцій до релізу
- раннє виявлення регресій
- Типовий процес
- відкрив PR -> автоматично створився preview URL
- QA/PM/design перевірили сценарії
- після approve merge в main
- Практика
- окремі preview env variables
- smoke tests проти preview URL
- чітка політика доступу до preview
Коротко:
- Preview deployment дає ізольоване середовище на кожен PR.
- Це покращує якість review і знижує ризик релізу.
- Добре працює в парі з автоматичними smoke checks.
99. Як Next.js інтегрується з CI/CD?
Next.js інтегрується в CI/CD як стандартний web-build pipeline: install -> lint -> typecheck -> test -> build -> deploy.
- Типовий pipeline
- перевірки якості (ESLint, TypeScript)
- юніт/інтеграційні тести
next build- деплой у preview/prod середовища
- Що важливо додати
- blocking checks для PR
- security scanning залежностей
- release gates для production
- Для стабільності
- однакові Node/toolchain версії
- cache залежностей у CI
- rollback стратегія
Коротко:
- CI/CD для Next.js це автоматизований quality gate + build + deploy.
- Ключове: незмінні перевірки перед merge та прод-релізом.
- Pipeline має бути відтворюваним і передбачуваним.
100. Які архітектурні рішення роблять Next.js-застосунок стабільним у довгостроковій перспективі?
Довгострокова стабільність у Next.js досягається поєднанням server-first архітектури, чітких модульних меж і жорсткої інженерної дисципліни.
- Архітектурний фундамент
- App Router + Server Components за замовчуванням
- мінімальний
'use client' - централізований server layer для auth/integrations
- Керування даними
- явна cache/revalidation стратегія на рівні маршрутів
- контрольовані мутації через Server Actions/Route Handlers
- стандартизована обробка помилок
- Командна масштабованість
- domain-driven структура
- code ownership і технічні стандарти
- обов'язкові тести та CI gates
- Операційна надійність
- спостережуваність (logs/metrics/tracing)
- preview deployments + поступові релізи
- чіткий rollback і incident-процес
Коротко:
- Стабільність дає не один патерн, а системна архітектура + процеси.
- Server-first, чіткі модулі, стандартизовані дані й помилки.
- Без дисципліни CI/тестів/моніторингу довгострокова якість не тримається.