Server и Client Components
Когда нужен 'use client' и как данные переходят границу.
Обновлено
Что такое Server Components и Client Components
В Next.js каждый компонент выполняется либо на сервере, либо в браузере (и на сервере при первом рендере). Выбор определяет, что компонент умеет и сколько JavaScript получит пользователь.
- Server Component — выполняется только на сервере. Его код никогда не попадает в браузер; пользователь получает только итоговый HTML.
- Client Component — отправляется в браузер как JavaScript, гидратируется и может быть интерактивным.
В app/ любой компонент по умолчанию — Server Component. Он становится Client Component, когда файл начинается с 'use client'.
Различия
| Server Component | Client Component | |
|---|---|---|
| Выполняется | только на сервере | сервер (начальный HTML) + браузер |
| JS, отправляемый в браузер | ноль | код компонента + зависимости |
async / await напрямую |
да | нет |
| Доступ к БД, файлам, секретам | да | нет |
useState, useEffect, хуки |
нет | да |
onClick, onChange |
нет | да |
window, localStorage |
нет | да |
Когда что использовать
| Нужно... | Выбор |
|---|---|
| прочитать данные (БД, API) и показать их | Server |
| статический контент: текст, раскладка, списки | Server |
| секреты (API-ключи, URL базы) | Server |
| состояние, эффекты, обработчики событий | Client |
| API браузера (localStorage, геолокация) | Client |
| библиотеки на хуках (графики, редакторы) | Client |
// Server Component — по умолчанию
export default async function Page() {
const posts = await db.post.findMany()
return <PostList posts={posts} />
}'use client'
import { useState } from 'react'
export function LikeButton({ initial }: { initial: number }) {
const [likes, setLikes] = useState(initial)
return <button onClick={() => setLikes(likes + 1)}>♥ {likes}</button>
}Золотое правило
Держите 'use client' как можно ниже в дереве. Страница остаётся серверной; клиентской будет только интерактивная кнопка. 'use client' отмечает границу: файл и всё, что он импортирует, становится клиентским кодом.
PageserverHeaderserverPostListserverLikeButtonclient — только это попадает в браузер как JS
Footerserver
Граница server → client
| Правило | Подробности |
|---|---|
| Данные передаются через props | они должны быть сериализуемыми: строки, числа, простые объекты, массивы, Date, Promise |
| Нельзя передавать функции в props | исключение — Server Actions |
Client может получать Server Components как children |
<ClientModal><ServerContent /></ClientModal> |
| Client не может импортировать Server Component | получает его только как children / prop |
Server Actions — мутации с клиента
Функции 'use server', которые вы вызываете с клиента, но выполняются они на сервере, — для форм и мутаций. Урок Server Actions.
Коротко
- Server Component (по умолчанию): async, доступ к данным и секретам, ноль JS в браузере.
- Client Component (
'use client'): состояние, эффекты, события, API браузера. 'use client'как можно ниже; сериализуемые props через границу.