27.06.2024, edited 3.07.2024

Ograniczenia SSR w next.js

馃嵃

Trzynasta wersja nexta by艂a reklamowana jako rozwi膮zanie kompletne, w szczeg贸lno艣ci zacieraj膮ca granice mi臋dzy serwerowymi i klienckimi komponentami, umo偶liwiaj膮ca ich dowolne przeplatanie. Sam testowa艂em j膮 i opisa艂em swoje do艣wiadczenia w tym po艣cie z grudnia 2023. Ju偶 wtedy zauwa偶y艂em, 偶e w konsoli s膮 jakie艣 nieznane mi warningi, ale nie przej膮艂em si臋 tym, bo zwykle tego typu ostrze偶enia to drobnostki 艂atwe i szybkie do naprawienia.

Jednak偶e, gdy wr贸ci艂em do tematu nieco p贸藕niej, w komercyjnym projekcie, to przekona艂em si臋, 偶e tu ostrze偶enia przekazuj膮 nam co艣 istotniejszego, bowiem m贸wi膮 o u偶yciu API biblioteki w niewspierany spos贸b.

Owe ostrze偶enia wygl膮daj膮 mniej wi臋cej tak:

clientWrapper.tsx:27 Warning: Cannot update a component (`Router`) while rendering a different component (`ClientWrapper`).
To locate the bad setState() call inside `ClientWrapper`,
follow the stack trace as described in https://reactjs.org/link/setstate-in-render

A problem 贸w pojawia si臋, gdy pr贸bujemy zawo艂a膰 komponent serwerowy w komponencie klienckim jak poni偶ej:

function ClientComponent({ ServerComponent }) {
  return (
    <>
      <Suspense fallback={'loading'}>
        <ServerComponent />
        // or {ServerComponent()}
      </Suspense>
    </>
  );
}

Dokumentacja wspomina, 偶e wspierane jest:

Passing Server Components to Client Components as Props

Jednak偶e jest to prawd膮 jedynie wtedy, gdy serwerowy komponent wo艂amy na serwerze i przekazujemy rezultat propsem do klienckiego komponentu, jak tu:

function ClientComponent({ serverComponentResult }) {
  return (
    <>
      <Suspense fallback={'loading'}>{serverComponentResult}</Suspense>
    </>
  );
}

Wydaje si臋 to jedynie drobnym ograniczeniem na pierwszy rzut oka, prawda? Co za r贸偶nica?

Ano taka, 偶e co wobec tego z serwerowym komponentem, kt贸ry zale偶y props贸w z klienta?

Powsta艂 ju偶 zreszt膮 na to topic na reddit鈥檆ie i wi臋kszo艣膰 dyskutuj膮cych zdaje si臋 zgadza膰, 偶e w tej sytuacji po prostu trzeba wo艂a膰 API, jak w SPA. Mo偶na nawet wo艂a膰 nextowe akcje, ale to API jest przecie偶 pomy艣lane do mutowania, wi臋c dla mnie to w pewnym sensie jeszcze gorsze rozwi膮zanie.

Czuj臋 si臋 wi臋c nieco rozczarowany, bo liczy艂em na co艣 por贸wnywalnego do mo偶liwo艣ci Hotwire i LiveView, gdzie w ramach wsparcia s艂ynnego strumieniowania komponent贸w (component streaming) m贸g艂bym dosta膰 na kliencie wst臋pnie zrenderowany komponent, zamiast wo艂a膰 endpoint itd.

Czy nadzieja umar艂a? W艂a艣ciwie, to nie jestem pewien. Cofnijmy si臋 na moment. Jak ju偶 wspomnia艂em, jest warning, niemniej jako艣 dzia艂a.

Co wi臋cej, po艣wi臋ci艂em troch臋 czasu i uda艂o mi si臋 pozby膰 tego ostrze偶enia, jak i rozwi膮za膰 pewnie pomniejsze problemy, kt贸re napotka艂em u偶ywaj膮c API w niewspierany (rzekomo) spos贸b.

Mo偶na to znale藕膰 tu. Wiem, 偶e kod jest paskudny (jak to workaround), ale fakt, 偶e dzia艂a sprawia, 偶e my艣l臋, czy mo偶e jest planowane oficjalne wsparcie dla tej funkcjonalno艣ci w przysz艂o艣ci.

Trzymam za to kciuki, bo jest to dla mnie element poszerzania granic, a wi臋c umo偶liwiania pisania kodu tak, jak nam to najlepiej pasuje.

Pozdro i do nast臋pnego 馃枛