Паралельне та послідовне отримання даних у Next.js
Шаблони отримання даних у Next.js
Як ви структурируєте отримання даних, значно впливає на продуктивність завантаження сторінки. Компоненти сервера Next.js підтримують як паралельні, так і послідовні шаблони.
Послідовне отримання даних (Waterfall)
Кожен запит чекає, поки завершиться попередній:
// ❌ Послідовне — повільно! Кожен запит чекає на попередній
async function UserProfile({ userId }: { userId: string }) {
const user = await getUser(userId); // 200ms
const posts = await getUserPosts(user.id); // 300ms (чекає на користувача)
const followers = await getFollowers(user.id); // 200ms (чекає на пости)
// Всього: ~700ms (200 + 300 + 200)
return (
<div>
<h1>{user.name}</h1>
<PostList posts={posts} />
<FollowerList followers={followers} />
</div>
);
}Паралельне отримання даних
Отримуйте всі дані одночасно з Promise.all:
// ✅ Паралельне — швидко! Усі запити починаються одночасно
async function UserProfile({ userId }: { userId: string }) {
const [user, posts, followers] = await Promise.all([
getUser(userId), // 200ms
getUserPosts(userId), // 300ms (починається одночасно)
getFollowers(userId), // 200ms (починається одночасно)
]);
// Всього: ~300ms (максимум з усіх трьох)
return (
<div>
<h1>{user.name}</h1>
<PostList posts={posts} />
<FollowerList followers={followers} />
</div>
);
}Паралельне отримання даних на рівні компонентів
Нехай кожен компонент отримує свої дані — Next.js обробляє їх паралельно:
// Батьківський компонент — без отримання даних тут
export default function Dashboard() {
return (
<div>
<UserStats /> {/* отримує незалежно */}
<RecentOrders /> {/* отримує незалежно */}
<Notifications /> {/* отримує незалежно */}
</div>
);
}
// Кожен дочірній компонент отримує свої дані
async function UserStats() {
const stats = await getStats(); // Виконується паралельно з іншими
return <StatsCard stats={stats} />;
}
async function RecentOrders() {
const orders = await getOrders(); // Виконується паралельно
return <OrderList orders={orders} />;
}
async function Notifications() {
const notifs = await getNotifications(); // Виконується паралельно
return <NotifList notifications={notifs} />;
}Стрімінг з Suspense
Показуйте контент поступово в міру надходження даних:
import { Suspense } from "react";
export default function Dashboard() {
return (
<div>
{/* Показує відразу */}
<h1>Dashboard</h1>
{/* Показує скелетон, а потім реальний контент, коли готовий */}
<Suspense fallback={<StatsSkeleton />}>
<UserStats />
</Suspense>
<Suspense fallback={<OrdersSkeleton />}>
<RecentOrders />
</Suspense>
<Suspense fallback={<NotifsSkeleton />}>
<Notifications />
</Suspense>
</div>
);
}Переваги стрімінгу:
- Користувачі бачать контент одразу (немає пустої сторінки)
- Швидкий контент з'являється першим, повільний контент надходить пізніше
- Кожен розділ має свій власний стан завантаження
Коли існують залежності
Іноді вам потрібно послідовне отримання:
async function UserProfile({ userId }: { userId: string }) {
// Крок 1: Спочатку потрібно отримати користувача (потрібен user.teamId)
const user = await getUser(userId);
// Крок 2: Тепер отримуйте паралельно, використовуючи дані користувача
const [team, posts] = await Promise.all([
getTeam(user.teamId), // Потрібен user.teamId
getUserPosts(user.id), // Потрібен user.id
]);
return (
<div>
<h1>{user.name}</h1>
<TeamInfo team={team} />
<PostList posts={posts} />
</div>
);
}Резюме
| Шаблон | Коли | Продуктивність |
|---|---|---|
| Послідовний | Дані залежать від попереднього результату | Найповільніший (waterfall) |
Promise.all | Незалежні дані в одному компоненті | Швидко |
| Рівень компонентів | Кожен компонент володіє своїми даними | Швидко + стрімінг |
| Suspense + стрімінг | Поступове завантаження | Найкращий UX |
Важливо:
Завжди надавайте перевагу паралельному отриманню при незалежних запитах. Використовуйте Promise.all в одному компоненті або розділіть отримання даних на окремі компоненти. Додавайте межі Suspense для поступового завантаження. Використовуйте послідовне отримання тільки тоді, коли один запит дійсно залежить від результату іншого.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.