DFIELDSOLUTIONS

Az archívumból

LaborServer vs. kliens komponensek 2026: a döntési szabályunk

Két év RSC-szállítás után a döntési szabályunk végre stabil: a magyar ügyfeleknél felmerülő tipikus dilemmák, a már megfizetett hibák, a határvonal-tervezés.

Az archívumból7 rész · 5 percÍrta: Dezső Mező · Megjelent .mdReactNext.jsRSCPerformanceArchitecture

Két év éles RSC-szállítás után végre megnyugodott a gyomorérzet. A magyar csapatok nagy része még mindig vallásként kezeli a kérdést · 'mi RSC-bolt vagyunk' vagy 'csak rakd rá a 'use client'-et, megy'. Mindkettő pénzt költ feleslegesen. A valódi szabály rövidebb, mint amit bármelyik tábor szeret hallani.

Default minden komponens Server Component, és csak akkor promóváljuk kliensre, ha a négy konkrét trigger közül valamelyik tűzbe lép. Ennyi az egész szabály. A poszt többi része a négy trigger, a rossz döntés ára, és az az eset, amikor a helyes válasz az, hogy 'egyik sem, telepítsd újra a határvonalat'.

01A default a szerver

Ha egy komponens adatot rendel, layoutot rajzol, másik komponenseket komponál, vagy adatbázist hív · az Server Component. Nincs state, nincs useEffect, nincs event handler · csak async függvény és JSX. A 'use client' kártyára, listára, layoutra, section header-re már nem reflexből kerül. Ez a szokás a Pages Router évekből maradt, és JS-t szállít a semmiért.

02A négy trigger, ami kliensre promóvál

  1. Kell useState, useReducer, useContext vagy bármilyen, render-ek között megmaradó hook. Controlled input. Modal, ami nyílik. Tab, ami vált.
  2. Böngésző-API-t hív: window, document, navigator, IntersectionObserver, requestAnimationFrame, localStorage, geolocation, web worker.
  3. Olyan harmadik fél lib-et használ, ami csak böngésző-entry pontból tölthető · legtöbb térkép, rich-text editor, chart-lib.
  4. Olyan interakciót kezel, amit a szerver nem tud előrendelni · onClick, onChange, drag-drop, focus trap.

Minden más szerver. Ha a '4' és 'ez csak egy link' között bizonytalan vagy, a válasz a szerver · a link <a href>, nem onClick handler.

03Az ár, amikor rosszul döntünk

Egy szervernek szánt komponens kliensre tolva: extra JS letöltés, parse, hidratáció. Minden prop, ami átkerül a határvonalon, szerializációs költség lesz. A szép komponálható fa hirtelen JSON blobot cipel, ami a HTML-lel együtt megy le. Két felesleges 'use client' egy layoutban: a marketing oldal 40KB bundle-t veszít a semmiért.

Egy kliensnek szánt komponens szerveren maradva: nem reagál, a felhasználó kattint és nem történik semmi, vagy a fejlesztő 'use client'-et tesz a szülőre, hogy 'megjavítsa'. Az utóbbi a legdrágább · most az egész részfa, beleértve a szerver-only gyerekeket is, kliens lesz, és újra kell írni.

04A határvonal a tervezési egység

Amit első nap nem mond senki: a szerver-kliens határvonal valódi architekturális artefakt. Megtervezed, megnevezed, kicsire tartod. Kliens-szigeteinket arról nevezzük el, amit csinálnak · <TabsClient>, <EditorClient>, <MapClient>. A szerver-wrapper mellettük marad komponálható és adat-fetchelő. Bármi más zagyvaság.

// app/dashboard/page.tsx · szerver
import { TabsClient } from "./tabs-client";
import { fetchSummary, fetchActivity } from "@/lib/data";

export default async function Page() {
  const [summary, activity] = await Promise.all([
    fetchSummary(),
    fetchActivity(),
  ]);

  return (
    <section>
      <h1>Dashboard</h1>
      <TabsClient
        summary={<SummaryView data={summary} />}
        activity={<ActivityList items={activity} />}
      />
    </section>
  );
}
// app/dashboard/tabs-client.tsx
'use client';
import { useState, type ReactNode } from "react";

export function TabsClient({ summary, activity }: { summary: ReactNode; activity: ReactNode }) {
  const [tab, setTab] = useState<"summary" | "activity">("summary");
  return (
    <>
      <nav role="tablist">
        <button onClick={() => setTab("summary")}>Összegzés</button>
        <button onClick={() => setTab("activity")}>Aktivitás</button>
      </nav>
      {tab === "summary" ? summary : activity}
    </>
  );
}

Figyeld meg, mi van a kliens-fájlban: state, két gomb, egy switch. Ennyi. A tab-ek tartalma szerver-komponens, prop-ként átadva. Az adatlekérést nem visszük át a határvonalon, csak slot-okat.

05Három minta, amit hetente használunk

A · Szerver adat, kliens interakció

Szerveren fetchelünk, kis kliens-szigetnek átadjuk az eredményt. Filter, tab, drawer, accordion. Az interaktív felület apró marad.

B · Server actions mutációkra

A form szerver-komponens. A submit server action. Az optimistic UI egy kis kliens-wrapperben él a form körül. A 'use client' direktívák száma egy marad.

C · Kliens-sziget böngésző-only lib-eknek

Térkép, chart, rich-text editor: dinamikus import egy kliens-komponensen belül. Wrap <Suspense>-be, hogy az oldal többi része ne várjon. A környező keretet a szerver rendereli.

06Csapdák, amibe belefutsz (mi is)

  • 'use client' a layouton, mert egy nav-elem interaktív · most minden oldal kliens-fa. Megoldás: tedd lejjebb a direktívát, a legkisebb interaktív részre.
  • Date vagy Map átadása a határvonalon, és csodálkozás, hogy a kliens stringet kap. A szerializációs szerződés JSON-szerű · stringify + parse mentálisan, mielőtt szállítasz.
  • Context provider kliens-komponensben, fogyasztó szerver-komponensben. Nem fog menni. Tedd át a fogyasztót kliensre, vagy cseréld a contextet prop-drillingre a határnál.
  • Korlát nélküli async a szerveren · egy lassú API blokkolja az oldalt. <Suspense> valódi fallbackkel, ne legyen 'pörgő-spinner-a-halálig'.
  • Felejtsd el, hogy a 'use client' 'csak kliensen rendel' jelent. Még mindig pre-rendel a szerveren, hacsak ki nem kapcsolod · a direktíva a határt jelöli, nem a runtime-ot.

07Amikor egyik sem érződik jónak · újra a határvonal

Ha küzdesz a határral, valószínűleg két dolgot kolokáltál, ami testvér kéne legyen. Bontsd a fát. A minta: szerver-komponens, ami fetchel és layoutol, plusz mellette egy kliens-komponens, ami az interakciót viszi, közöttük children vagy render-prop slot. Elég ilyen után már nem reflexből nyúlsz a 'use client'-ért.

Nézd meg a bundle-t. Ha egy marketing-jellegű oldal több mint 80KB kliens JS-t szállít, valami 'use client'-et visel, ami nem kéne. Tíz perc bundle analyzerrel szinte biztosan kiesik.

Az összegzés egy post-it-en: szerver default, valódi triggerre promóválj, a kliens-szigetet kicsire tartsd, és a határt úgy tervezd, mint egy publikus API-t. Két év után még mindig többet törlünk 'use client'-et, mint amennyit hozzáadunk.

Amit érdemes elvinni

  • Default minden komponens Server Component. Csak akkor promóváljuk kliensre, ha az alábbi négy közül valamelyik trigger valódi: state, böngésző-API, kizárólag kliens-oldali third-party lib, vagy szerver oldalról nem előrenderelhető interakció. A kliens-szigetet a lehető legkisebbre tartjuk · az ár nem a kódsor, hanem a bundle, a hidratáció és az INP.

Az írásban használt fogalmak

Ezt is megépítjükWebteljesítmény

Több a laborból

Összes bejegyzés

Megnézzük ugyanezt a te rendszereden?Kezdjünk bele

5,0
“Új webshop, több rendelés már az első héten.”Müller Márk · GeekCornerÜgyvezető · Magyarország