To understand the benefits of RSCs, I will briefly talk about Server Side rendering (SSR) and Suspense boundary.
SSR works on initial page load (When directly navigating to the page) by sending the pre-rendered HTML to the client which will be hydrated with the downloaded JavaScript to be fully interactive. However, with SSR the data must be fetched in the server before React can show any pre-rendered HTML. Also, all JavaScript should be downloaded on the client side before starting the hydration and the hydration process should be completed before the page can become interactive.
To solve these issues, React introduced Suspense, which brings both server-side HTML streaming and selective hydration. So, by wrapping any component (generally heavy components) with , we are telling React to deprioritize that component's rendering and hydration, which will cause in loading other components without getting blocked by the heavier ones. However, even after using Suspense we still need to download all JavaScript to the client even if it's streamed to the browser asynchronously. Also, all heavy components will continue to be computed on the client.
By introducing React Server Components, React can now solve all the previous issue:
๐ Now we can move all heavy components to the server (which is powerful and physically closer to data sources) by using RSCs which will individually fetch data and then will be rendered entirely on the server. After that, the result of that rendering will be streamed into the client-side (React component tree), removing the need for client-side re-rendering.
๐ The result of rendering RSC on the server will be React Server Component Payload which contains beside the rendered result of RSC: a placeholders to define where Client Components should be rendered, the references to their JavaScript files and any props passed from a Server Component to a Client Component. Which will reduce the size of the client-side JavaScript bundle by resolving all dependencies on the server and sending only RSC Payload.
๐ Regarding Client Components, the hydration will happen concurrently with RSCs streaming in, because the compute load will be shared between client and server.
๐ Even when an RSC needs to be re-rendered because of state change, No hard refresh will be needed as RSC will be refreshed on the server and seamlessly merges into the existing DOM. Which will preserve the client state even if server components are updated from the server.
๐ก All code written for Server Components must be serializable, which means that we canโt use lifecycle hooks, such as useState or useEffect.
๐ก RSC does not replace SSR or Suspense, but it works with them to provide the best performance possible.
๐ก Typically we are using Server Components at the root level and it is preferred to fetch data in the Server Components (Server is physically closer to data sources and more powerful than client devices), then we can pass the result to other Server Component or to a Client Component if we need to use event handlers or lifecycle hooks.
๐ก We cannot import a Server Component into a Client Component but instead we can pass Server Components as a prop to a Client Component (usually using React children prop).
๐ก We can use RSCs with Next.js starting from version 13.4 (App Router).
๐๐ [Project on GitHub]: Nextjs 14 with App Router, Fully authentication using NextAuth ... (https://github.com/alaa-m1/nextjs14-approuter-nextauth-shopsfinder)
Top comments (3)
Thanks, for sharing with the community
Thanks for sharing ๐,
I've a question regarding authentication..
I've a Nextjs14 app which I will integrate with a PHP server usually I store JWT at localstorage and send it with all client side requests but of course it's not accessible on server side.
Is there a way I can store it on server side and use it on server side components ?
Thanks in advance.
@a_m_h_gad
If I'm not mistaken you can do this with the header-cookies functions of next: nextjs.org/docs/app/api-reference/...
Set your cookie from a server action and read it in your page.tsx route, or in your middleware.