joplin-notes/joplin notion extension/Web Development/React/next/Coding 8 (Rendering).md
2026-11-04 00:33:23 +05:30

380 lines
16 KiB
Markdown

Coding 8 (Rendering)
RSC in detail https://www.youtube.com/watch?v=X2eUQIjNxCQ
- Rendering is the rocess that transforms the code we write into user interfaces
- choosing right time and place for renering is key for performant application
- CSR (Client Side Rendering), SSR (Server Side Rendering), RSC(React Server Components)
### Rendering in React
- when client requests for web page it gets html + js file and html file is mostly blank and have link to js file
- **Client side rendering**
- Method of rendering where compoent code is transformed to user interface directly within the brower is known as client side rendering
- ![dda32c58411fd49ead491fe54ceaf0b5.png](../../../../_resources/dda32c58411fd49ead491fe54ceaf0b5.png)
- It became standard for SPAs(Single Page Apps)
- Drawbacks of CSR
- SEO : Generating HTML that mainly contains a single div tagis not optimal for SEO, as it provides little content for search engines to index
- Performance : Having browser handle all the work, fetcjing data, computing UI and making the HTML interactive can slow things down so users might see a blank screen or loading spinner while page loads
- Each new feature added to applicaton increases size of js bundle prolonging the wait time for users to see the UI and this delay is noticed by users with slow internet connection
- **Server side Rendering**(SSR)
- To overcome drawbacks of CSR, gatsby and next started to use SSR.
- ![0582a9e09684b83265f88c682b64d183.png](../../../../_resources/0582a9e09684b83265f88c682b64d183.png)
- Even though some problems related to SEO and performance was solved UI was still non interactive and for that Js reference is used
- Hydration
- Hydration is the process of attaching event listeners to the DOM, to make the static HTML interactive. Behind the scenes, hydration is done with the hydrateRoot
React API.
- When static html is served then react takes control in browser reconstructing component tree in memory
- It carefully plans the placement of interactive elements within this tree and react proceeds to bind necessary js logic to these elementsonalities required for a ully interactive iser experience
- This involves initializing application statem attaching event handlers for actions like click and mouseovers, setting up dynamic functionalities required for interactive User experience
- ![37fd67ae56fd0f4487e84586dc8630e2.png](../../../../_resources/37fd67ae56fd0f4487e84586dc8630e2.png)
- Server side solutions
1. Static Site Generation : When the application is deployed to the server which results in pages that are already rendered and ready to serve . It is ideal for content that doesnt change often like blog posts.
2. Server side rendering : Renders pages on demand in response to user requests . Sutable for personalized content where the HTML depends on the logged in user.
Server-Side Rendering was a significant improvement over CSR
- **Drawbacks of SSR** (All or Nothing waterfall)
1. You have to fetch everything before you can show anything
- Components cannot start rendering and then pause or wait while data is being loaded.
- If a component needs to fetch data from database or another source(like API) then fetching must be completed before the server can behin rendering the page
- This can delay server's response time to browser as server must finish collecting all necessary data before any part of page can be sent to client
2. We have to load everything before we can hydrate anything
- For successful hydration, where react adds interactivity to server rendered HTML, component tree must match exactly of server generated component tree
- This means all JS for components must be loaded on client befire we can start hydrating any of them
3. We have to hydrate everything before u can interact with anything
- As React hydrates component tree in single pass means all components must be hydrated before they can be interacted with any of them
4. Summary
- load data for entire page for viewing
- load js for entire page
- hydrate entire page
5. It is inefficient if some parts of app is slower than others as often with real world apps
 
### Suspense SSR Architecture
- To combat all or nothing waterfall of SSR `<suspense>` component can be used which unlock 2 major SSR features
1. HTML streaming on the server
2. Selective hydration on the client
Rendering components without suspense
![76e14ea51e7166b22c55f3cd00ee55c3.png](../../../../_resources/76e14ea51e7166b22c55f3cd00ee55c3.png)
&nbsp;
**Rendering components with suspense**
![59186eb638f7630a7eb38bc5aa9a873a.png](../../../../_resources/59186eb638f7630a7eb38bc5aa9a873a.png)
- So html streaming will occur and once the server is ready for data for main section with inline script tag which contains minmal js to position that component so that it will be visible for ths user
This solve 2 problems ie
- No need to fetch everything before to show anything
- if particular section delays the initial html then it can seemlessly inthegrated to stream later.
- this is how it faciliates server side html streaming
Remaining challenges
- client side hydration cant start unless the js of main section is loaded
- and if the js bundle for the main section is large then it will delay process significantly
As html streaming section is solved but we also need to load js separtely for main section so other section can become interactive too and dont wait for main component
&nbsp;
**Code rendering**
- Code splitting allows us to mark specific code segments as not immediately necessary for loading, signalling your bundler to segregate them into separate `<scripts>` tags.
- Using `React.lazy` for code splitting enables you to separate the main section's code from primary js bindle
- The js containing React and the code for the entire application, excluding the main section can now be downloaded independently by the client without having to wait for main section's code.
for the following architecture
```text
src/app
about
Main.jsx
page.jsx
```
In `src/app/about/Page.jsx`
```js
"use client";
// function promiseSetTimeOut(time) {
// return new Promise((resolve, reject) => {
// setTimeout(() => {
// resolve();
// }, time);
// });
// }
function delayForDemo(promise) {
return new Promise((resolve) => {
setTimeout(resolve, 3000);
}).then(() => promise);
}
import { Suspense, lazy } from "react";
// Main component will be loaded 3s later
const Main = lazy(() => delayForDemo(import("./Main")));
export default function DashBoard() {
console.log("page loaded");
// const getDatainDelay = async (time, data) => {
// await promiseSetTimeOut(time);
// // return <button onClick={clickHandler}>data</button>;
// return <button>data</button>;
// };
return (
<>
<header>
<h1>Dashboard</h1>
</header>
<Suspense fallback={<button>Loading..</button>}>
{/* <main>{getDatainDelay(500, "hey this is main loaded")}</main> */}
<Main />
</Suspense>
<footer>copyright by nextjs</footer>
</>
);
}
```
In `src/app/about/Main.jsx`
```js
export default function Main() {
console.log("main loaded");
return <div className="Main">ghh</div>;
}
```
Selective hydration on the Client
- Wrapping the main section with `Suspense` rest of page will not be prevented from streaming and hydrating
- ![e39413e48b0043e492bc1dc3ee14600f.png](../../../../_resources/e39413e48b0043e492bc1dc3ee14600f.png)
&nbsp;
Drawbacks of Suspense SSR
- In react there is CSR so even if there is non interactive UI it will needs to undergo hydration
&nbsp;
## React Server Components (RSC)
- It is new architecture designed by React team
- The approach aims to leverage the strnegths of both server and client environments optimizing for efficiency
- It introduces a dual component model
- client components
- server components
- The distinction is not based on functionality of the components but rather on where they execute and specific environments they are designed to interact with.
&nbsp;
RSC and Next.js
- App router in Next.js is built on the RSC architecture
&nbsp;
### RSC Rendering Lifecycle
**RSC Loading Sequence**
![3d430e984fae82dde78badf4b729f50b.png](../../../../_resources/3d430e984fae82dde78badf4b729f50b.png)
https://nextjs.org/docs/app/building-your-application/rendering/client-components
- Browser sends request to the server about route.
- Nextjs recieves the request and match server component(SC) respective for the route
- Nextjs instructs react to render server component
- React render the server component and any child component that r part of server component converting them to RSC payload.
If any of server component suspends then react pauses rendering of subtree (child components along with it) and sends a placeholder value instead meanwhile client components are prepared with instructions for later in the life cycle.
- This RSC payload is used by next which contains client component instruction to generate HTML for both components(client and server) on the server for the route
- Generated html is streamed to the client along with RSC payload which reconcile the client and server components in order to update the DOM ie progressively render UI. this checking/matching of server and client component trees (ensures that the client-side representation of a component matches the server-side-rendered HTML that was initially sent to the browser. ) is important for maintaining consistency.
- Finally hydration happens which converts it into interactive UI by attaching event listeners
&nbsp;
**RSC Update Sequence**
Related to refresing parts of the app
![f260be10c48c6fd437878a1074e7bb3a.png](../../../../_resources/f260be10c48c6fd437878a1074e7bb3a.png)
- Browser requests refetch of specic UI such as a full route.
- Next matches SC component and instruct react to render server component and react render components like the initial loading step.
- Unlike initial loading there is no HTML generation and this RSC payload is progressively streamed back to client
- On recieving route is re rendered using this RSC payload which is then reconiled and merged with new rendered output with existing component on screen.
- This UI description is in JSON format and not HTML, react can update DOM while preserving crucial UI updates such as focus or input values.
&nbsp;
## Server rendering Strategies
- Static rendering
- Dynamic rendering
- Streaming
&nbsp;
### Static rendering
- Generate HTML pages at time of building our applications. Means all data and content of web page is prepared in advanced.
- This approach means results can be cached by CDN and served to client instantly
- Able to share the rendered work to different users resulting in significant performace boost for application
- Useful for blogs, e-commerce product pages, documentation and marketing pages
&nbsp;
**How to Statically Render?**
- It is default rendering strategy in the app router and all routes are automatically prepared at build time without additional setup
&nbsp;
Production vs Dev Server
- For production,an optimized build is created once
- In development it is inefficient to build app after every changes
- in production builds, page is pre-rendered once build command is run
- in development mode, page will be pre-rendered for every request.
.next folder
- when building this is the output we get this
![6ab5db7b6fde89f907e0509a40c873d9.png](../../../../_resources/6ab5db7b6fde89f907e0509a40c873d9.png)
- The size is the amount of assets downloaded to perform a client-side transition to that page (after you've paid the "first load" for a different page). Means when we go from page A to B then the assets required which is basically difference as for navigating not all the assets is required as most of them r initially loaded
- First Load JS is the total amount of assets your users will download when visiting the page from the server instead of navigating as initially nothing is loaded.
- First load js is the important metric for performance
https://github.com/vercel/next.js/pull/12034
https://github.com/vercel/next.js/issues/10565
`.rsc` files
- these are the compact string representation of virtual DOM and includes abbreviations, internal references and encoded special meanings
- for the server components these `.rsc` files contain text which is displayed on web page too. Means it include rendered result of server component
![cc82dca645b175b114ebd8e370002060.png](../../../../_resources/cc82dca645b175b114ebd8e370002060.png)
- for the client components it contains placeholders/instructions instead means a refernce to chunks js file.
![b07c69aa4466bb2fc84630297b41983a.png](../../../../_resources/b07c69aa4466bb2fc84630297b41983a.png)
- This chunk js file referened by client component rsc is necessary for reconcilation and hydration
&nbsp;
**Prefetching**
- Prefetching is a technique used to preload a route in the background before the user navigates to it
- Routes are fetched automatically as they become visible in user's viewport when page first loads or it comes to view through scrolling
- For static routes, entire route is prefetched and catched by default.
- When homepage is loaded, nextjs prefetches the route whose links are there in homepage means `Link` components with those routes
&nbsp;
### Dynamic rendering
- It is server rendering strategy where routes are rendered separately for each user at a request time
- Useful when a route has personalized data or cookies info or url search params that can only be known at request time.
- News website, personalized e-commerce pages and social media feeds
&nbsp;
**How to dynamically render**
- During rendering, if dynmaic function is discovered then nextjs will switch to dynmaic rendering for whole route
- In nextjs fynmaic functions are `cookies()`, `headers()` and `searchParams` and using any of these will switch to dynamic rendering at request time for the route.
Structure
```text
src/app
static
page.jsx
about
page.jsx
layout.jsx
page.jsx
```
In `src/app/static/page.jsx`
```js
import { cookies } from "next/headers";
export default function Static() {
// to force dynamaic rendering
const cookieStore = cookies();
const theme = cookieStore.get("theme");
console.log("theme: ", theme);
return (
<div className="Static">
<h1>Static</h1>
</div>
);
}
```
- After building we get this output in terminal
![7c2152bc0ec8f03902aded1280ca0afc.png](../../../../_resources/7c2152bc0ec8f03902aded1280ca0afc.png)
This `/static` route will be dynmiacally rendered means it will not be rendered on build but rendered on nodejs when request is made
Also in `.next` there will be no `static.html` like about and root route have
&nbsp;
### Streaming
- Streaming is a strategy for allowing for progressive UI rendering from the server.
- Work is divided into chunks and streamed to client as soon its ready
- Enables users to get intitial look immediately and wait for whole page to load progressively
- Streaming is integrated into nexjs app router by default
```text
src/app
product-detail
page.jsx
components
product.jsx
reviews.jsx
layout.jsx
page.jsx
```
In `src/app/components/product.jsx`
```js
const DELAYTIME = 2000;
export async function Product() {
await new Promise((resolve) => setTimeout(resolve, DELAYTIME));
return <div>Product</div>;
}
```
In `src/app/components/reviews.jsx`
```js
const DELAYTIME = 4000;
export async function Reviews() {
await new Promise((resolve) => setTimeout(resolve, DELAYTIME));
return <div>Reviews</div>;
}
```
In `src/app/product-detail/page.jsx`
Without using suspense
```js
import { Product } from "../components/product";
import { Reviews } from "../components/reviews";
export default function ProductDetail() {
return (
<div>
<h1>Product Detail Page</h1>
<Product />
<Reviews />
</div>
);
}
```
The page will take 4s to load bcz the reviews page is taking that much time and page will only load once all the component is rendered.
So to have a fallback till those components are loaded so that user can see the page atleast use suspense
With suspense
```js
import { Suspense } from "react";
import { Product } from "../components/product";
import { Reviews } from "../components/reviews";
export default function ProductDetail() {
return (
<div>
<h1>Product Detail Page</h1>
<Suspense fallback={<p>Loading Product...</p>}>
<Product />
</Suspense>
<Suspense fallback={<p>Loading Reviews...</p>}>
<Reviews />
</Suspense>
</div>
);
}
```