Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

Streaming SSR i Edge Runtime

Wyobraz sobie, ze zamiast wysylac caly statek kosmiczny jednym transportem, wysylasz go modul po module - kokpit natychmiast, a systemy nawigacyjne i ladownie dolatuja w tle. Dokladnie tak dziala Streaming SSR - serwer zaczyna wysylac HTML do przegladarki jeszcze zanim caly rendering zostanie ukonczony. A Edge Runtime przenosi ten proces blizej uzytkownika - jak stacje przekaznikowe rozmieszczone po calej galaktyce.

Tradycyjny SSR vs Streaming SSR

Tradycyjny SSR generuje caly HTML na serwerze, zanim wyslije go do przegladarki. Uzytkownik czeka na najwolniejszy komponent:

1// Tradycyjny SSR - uzytkownik czeka na WSZYSTKO
2// Serwer: [renderuj Header][renderuj Dane][renderuj Footer] -> wyslij calosc
3// Czas: 500ms + 2000ms + 100ms = 2600ms zanim cokolwiek zobaczy
4
5// Streaming SSR - fragmenty wysylane natychmiast
6// Serwer: [Header gotowy] -> wyslij! [Dane gotowe] -> wyslij! [Footer] -> wyslij!
7// Czas: 500ms do pierwszego fragmentu, reszta dochodzi w tle

renderToPipeableStream - API streamingu

React 18 wprowadza

renderToPipeableStream
jako nastepce
renderToString
:

1import { renderToPipeableStream } from 'react-dom/server';
2
3// Serwer Node.js z Streaming SSR
4app.get('/', (req, res) => {
5  const { pipe } = renderToPipeableStream(
6    <App />,
7    {
8      bootstrapScripts: ['/main.js'],
9      onShellReady() {
10        // Powloka (shell) gotowa - wyslij natychmiast
11        res.setHeader('Content-Type', 'text/html');
12        pipe(res);
13      },
14      onShellError(error) {
15        // Blad w krytycznej czesci - wyslij fallback
16        res.statusCode = 500;
17        res.send('<h1>Server Error</h1>');
18      },
19      onAllReady() {
20        // Wszystko gotowe (przydatne dla crawlerow/SEO)
21      },
22      onError(error) {
23        console.error('Streaming error:', error);
24      }
25    }
26  );
27});

onShellReady
jest wywolywany gdy glowna "powloka" strony jest gotowa - czyli wszystko poza granicami
<Suspense>
. Uzytkownik widzi szkielet strony natychmiast.

renderToReadableStream - Edge Runtime API

Dla Edge Runtime (Cloudflare Workers, Vercel Edge, Deno Deploy) uzywamy

renderToReadableStream
, ktore zwraca Web Streams API:

1import { renderToReadableStream } from 'react-dom/server';
2
3// Edge Runtime handler
4export default async function handler(request) {
5  const stream = await renderToReadableStream(
6    <App />,
7    {
8      bootstrapScripts: ['/main.js'],
9      onError(error) {
10        console.error('Edge streaming error:', error);
11      }
12    }
13  );
14
15  return new Response(stream, {
16    headers: { 'Content-Type': 'text/html' },
17  });
18}

Roznica miedzy API:

  • renderToPipeableStream
    - Node.js Streams (Node.js runtime)
  • renderToReadableStream
    - Web Streams API (Edge Runtime, Deno, przegladarki)

Suspense jako granica streamingu

<Suspense>
definiuje granice streamingu - serwer wysyla fallback i pozniej podmienia go na gotowy HTML:

1function SpaceStationDashboard() {
2  return (
3    <div>
4      {/* Renderowane natychmiast - czesc "shell" */}
5      <Header title="Stacja Kosmiczna Alpha" />
6      <Navigation />
7
8      {/* Kazda sekcja streamuje sie niezaleznie */}
9      <Suspense fallback={<Skeleton type="missions" />}>
10        <MissionList />  {/* Dane laduja 800ms */}
11      </Suspense>
12
13      <Suspense fallback={<Skeleton type="crew" />}>
14        <CrewStatus />   {/* Dane laduja 1500ms */}
15      </Suspense>
16
17      <Suspense fallback={<Skeleton type="telemetry" />}>
18        <TelemetryData />  {/* Dane laduja 2200ms */}
19      </Suspense>
20    </div>
21  );
22}
23
24// Przebieg streamingu:
25// 1. [0ms]    Serwer wysyla: Header + Navigation + 3x Skeleton
26// 2. [800ms]  Serwer dosyla: MissionList (podmienia Skeleton)
27// 3. [1500ms] Serwer dosyla: CrewStatus (podmienia Skeleton)
28// 4. [2200ms] Serwer dosyla: TelemetryData (podmienia Skeleton)

Edge Runtime - obliczenia blizej uzytkownika

Edge Runtime to srodowisko wykonawcze dzialajace na "krawedzi" sieci (edge) - blisko uzytkownika, na serwerach CDN rozlozonych globalnie. Zamiast jednego centralnego serwera, Twoja aplikacja dziala na setkach lokalizacji:

1// next.config.js - konfiguracja Edge Runtime w Next.js
2// W pliku strony:
3export const runtime = 'edge';
4
5// Lub w route handler:
6export const runtime = 'edge';
7
8export async function GET(request) {
9  // Ten kod wykonuje sie na edge (blisko uzytkownika)
10  const userLocation = request.geo?.city || 'Unknown';
11
12  return new Response(
13    JSON.stringify({ message: 'Hello from edge!', location: userLocation }),
14    { headers: { 'Content-Type': 'application/json' } }
15  );
16}

Roznice: Node.js vs Edge Runtime

| Cecha | Node.js Runtime | Edge Runtime | |-------|----------------|--------------| | Lokalizacja | Jeden region serwera | Globalnie rozproszony | | Cold start | 200-500ms | 1-5ms | | Rozmiar bundla | Bez limitu | ~1-4MB limit | | API | Pelne Node.js API | Ograniczone (Web APIs) | | Streaming | renderToPipeableStream | renderToReadableStream | | Bazy danych | Dowolne | Edge-compatible (Planetscale, Turso) |

Progressive Hydration

Streaming SSR naturalnie wspiera progressive hydration - React hydruje komponenty w miare ich pojawiania sie:

1// Schemat progressive hydration:
2// 1. Serwer streamuje HTML -> przegladarka wyswietla
3// 2. JavaScript sie laduje
4// 3. React hydruje komponenty ktore juz sa w DOM
5// 4. Nowe fragmenty HTML przychodza ze streamu
6// 5. React hydruje je natychmiast po otrzymaniu
7
8// Selective hydration - React priorytetyzuje
9// komponenty z ktorymi uzytkownik interaguje:
10function App() {
11  return (
12    <div>
13      {/* Uzytkownik kliknal tu - React hydruje to PIERWSZE */}
14      <Suspense fallback={<Skeleton />}>
15        <InteractivePanel />
16      </Suspense>
17
18      {/* To czeka w kolejce */}
19      <Suspense fallback={<Skeleton />}>
20        <HeavyDataTable />
21      </Suspense>
22    </div>
23  );
24}

Podsumowanie

Streaming SSR i Edge Runtime to potezne narzedzia przyspieszajace dostarczanie aplikacji:

  1. Streaming SSR - wysyla HTML fragmentami, uzytkownik widzi strone natychmiast
  2. renderToPipeableStream - API Node.js do streamingu
  3. renderToReadableStream - API Edge Runtime (Web Streams)
  4. Suspense boundaries - definiuja granice streamingu
  5. Edge Runtime - wykonywanie kodu blizej uzytkownika (niski latency, szybki cold start)
  6. Progressive Hydration - React hydruje komponenty w miare ich pojawiania sie

Streaming SSR zmienia dostarczanie aplikacji jak systemy modulowe na stacji kosmicznej - kazdy modul startuje niezaleznie, uzytkownik nie czeka na calosc.

Vai a CodeWorlds