<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Paweł Sobolewski</title>
    <description>The latest articles on DEV Community by Paweł Sobolewski (@pawe_sobolewski_1dcc746a).</description>
    <link>https://dev.to/pawe_sobolewski_1dcc746a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3312246%2Fca6ea4e0-c0a5-4d08-91cd-39e795ee2215.jpeg</url>
      <title>DEV Community: Paweł Sobolewski</title>
      <link>https://dev.to/pawe_sobolewski_1dcc746a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pawe_sobolewski_1dcc746a"/>
    <language>en</language>
    <item>
      <title>React Server and Client Components in Next.js: Understanding the Difference</title>
      <dc:creator>Paweł Sobolewski</dc:creator>
      <pubDate>Tue, 30 Dec 2025 23:00:00 +0000</pubDate>
      <link>https://dev.to/u11d/react-server-and-client-components-in-nextjs-understanding-the-difference-4bml</link>
      <guid>https://dev.to/u11d/react-server-and-client-components-in-nextjs-understanding-the-difference-4bml</guid>
      <description>&lt;p&gt;The React team introduced &lt;a href="https://react.dev/reference/rsc/server-components" rel="noopener noreferrer"&gt;&lt;strong&gt;Server Components&lt;/strong&gt;&lt;/a&gt; as an experimental feature in &lt;a href="https://react.dev/blog/2022/03/29/react-v18#server-components-is-still-in-development" rel="noopener noreferrer"&gt;React 18&lt;/a&gt;. They allow parts of a React application to render on the server, reducing the JavaScript sent to the client and enabling more efficient data fetching.&lt;/p&gt;

&lt;p&gt;Next.js &lt;a href="https://nextjs.org/docs/app/getting-started/server-and-client-components" rel="noopener noreferrer"&gt;adopted this concept&lt;/a&gt; and integrated it into its &lt;a href="https://nextjs.org/docs/app" rel="noopener noreferrer"&gt;&lt;strong&gt;App Router&lt;/strong&gt;&lt;/a&gt; (introduced in version 13). The framework combines React's server-rendering capabilities with its own routing, data fetching and performance optimizations.&lt;/p&gt;

&lt;p&gt;Server Components let developers build apps that are faster, more secure and easier to maintain—while still adding interactivity through Client Components where needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Server Components?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Server Components&lt;/strong&gt; run exclusively on the &lt;strong&gt;server&lt;/strong&gt;—they never execute in the browser and cannot use client-only features like &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;, or &lt;code&gt;window&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since they render on the server, they can securely fetch data from databases or APIs and send back only the resulting HTML to the client. This reduces bundle size and improves performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Characteristics:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Run only on the server&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exclude JavaScript&lt;/strong&gt; from the client bundle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetch data securely&lt;/strong&gt; without needing API routes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cannot use React state hooks&lt;/strong&gt; or browser APIs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can import Client Components&lt;/strong&gt;, but Client Components cannot import them&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This is a Server Component (default)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ServerComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, all components in the &lt;strong&gt;Next.js App Router&lt;/strong&gt; (&lt;code&gt;app/&lt;/code&gt; directory) are &lt;strong&gt;Server Components&lt;/strong&gt;, unless specified otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Client Components?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://react.dev/reference/rsc/use-client" rel="noopener noreferrer"&gt;&lt;strong&gt;Client Components&lt;/strong&gt;&lt;/a&gt; are traditional React components that run in the &lt;strong&gt;browser&lt;/strong&gt;. They're necessary when you need &lt;strong&gt;interactivity&lt;/strong&gt;, &lt;strong&gt;state&lt;/strong&gt;, or &lt;strong&gt;effects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To mark a file as a Client Component, add this directive at the top: &lt;code&gt;"use client";&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here's a common misconception: &lt;strong&gt;Client Components are still prerendered on the server&lt;/strong&gt;. During the initial render, Next.js generates HTML for them on the server—just like Server Components. Once the JavaScript bundle loads in the browser, React &lt;strong&gt;hydrates&lt;/strong&gt; these components, attaching event listeners and state to make them interactive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Clicked &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; times
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Important:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hydration errors&lt;/strong&gt; occur when the server-rendered HTML doesn't match what React renders in the browser—for example, when using &lt;code&gt;Math.random()&lt;/code&gt; or &lt;code&gt;Date.now()&lt;/code&gt; during render.&lt;/li&gt;
&lt;li&gt;Client Components &lt;strong&gt;cannot import Server Components&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;However, &lt;strong&gt;you can pass Server Components as props&lt;/strong&gt; to Client Components. React renders them on the server and includes them in the client-rendered tree (see below).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Combining Server and Client Components
&lt;/h2&gt;

&lt;p&gt;Next.js's true power lies in combining both component types effectively. You can fetch data on the server, then pass it to a client component for interactive rendering.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Server Component&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Counter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅ allowed (Client Component)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Passing Server Components as Props
&lt;/h3&gt;

&lt;p&gt;While &lt;strong&gt;Client Components cannot import Server Components&lt;/strong&gt;, a &lt;strong&gt;Server Component can pass another Server Component &lt;a href="https://nextjs.org/docs/app/getting-started/server-and-client-components" rel="noopener noreferrer"&gt;as a prop&lt;/a&gt;&lt;/strong&gt; to a Client Component.&lt;/p&gt;

&lt;p&gt;This works because the server renders the server-side part before sending it to the browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Server Component A&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ServerInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Server time: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Client Component&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"wrapper"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Wrapped content:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Server Page&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ServerInfo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./ServerInfo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Wrapper&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Wrapper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Wrapper&lt;/span&gt; &lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ServerInfo&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Wrapper&lt;/code&gt; is a Client Component.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;does not import&lt;/strong&gt; &lt;code&gt;ServerInfo&lt;/code&gt; directly.&lt;/li&gt;
&lt;li&gt;Instead, &lt;code&gt;ServerInfo&lt;/code&gt; is &lt;strong&gt;rendered on the server&lt;/strong&gt; and passed as a serialized React node through props.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pattern is powerful for &lt;strong&gt;composition&lt;/strong&gt;, &lt;strong&gt;layout customization&lt;/strong&gt;, and &lt;strong&gt;partial interactivity&lt;/strong&gt; in server-driven views.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hydration and Common Pitfalls
&lt;/h2&gt;

&lt;p&gt;Hydration is the process of React attaching interactivity to the static HTML produced by the server.&lt;/p&gt;

&lt;p&gt;It’s an essential step — but also a common source of confusion and bugs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Causes of Hydration Errors:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Non-deterministic rendering&lt;/strong&gt; — e.g., using &lt;code&gt;Math.random()&lt;/code&gt;, &lt;code&gt;Date.now()&lt;/code&gt;, or random IDs directly in render.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional rendering differences&lt;/strong&gt; between server and client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mismatched props&lt;/strong&gt; — if server and client data diverge during hydration.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How to Avoid Them:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use deterministic data in components that render both server- and client-side.&lt;/li&gt;
&lt;li&gt;Avoid rendering dynamic values that differ between server and client.&lt;/li&gt;
&lt;li&gt;Keep interactivity isolated in small, well-defined Client Components.&lt;/li&gt;
&lt;li&gt;Keep dynamic parts in “client only scope”, like useEffect hook&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Server Component&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Client Component&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Execution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Server only&lt;/td&gt;
&lt;td&gt;Server prerender + Browser hydration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Can use hooks (&lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Can fetch data securely&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;⚠️ via API routes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Imports direction&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Can import Client&lt;/td&gt;
&lt;td&gt;❌ Cannot import Server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Can receive Server Components as props&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bundle size impact&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;td&gt;Increases bundle size&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SEO&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Also good (since prerendered)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Typical use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Static content, data fetching&lt;/td&gt;
&lt;td&gt;Interactive UI, forms, animations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;React introduced the Server/Client component model, giving developers precise control over &lt;strong&gt;where and how&lt;/strong&gt; rendering happens. Next.js enhances this with routing, data fetching, and performance optimizations.&lt;/p&gt;

&lt;p&gt;To summarize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;Server Components&lt;/strong&gt; for data-heavy or static content.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Client Components&lt;/strong&gt; for interactivity.&lt;/li&gt;
&lt;li&gt;Client Components are &lt;strong&gt;prerendered&lt;/strong&gt; on the server, then &lt;strong&gt;hydrated&lt;/strong&gt; in the browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import flow:&lt;/strong&gt; Server → Client ✅, Client → Server ❌.&lt;/li&gt;
&lt;li&gt;However, &lt;strong&gt;Server Components can be passed to Client Components via props&lt;/strong&gt; ✅.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When used correctly, this architecture makes your app &lt;strong&gt;faster&lt;/strong&gt;, &lt;strong&gt;more secure&lt;/strong&gt;, and &lt;strong&gt;easier to maintain&lt;/strong&gt;—a true win for modern React development.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Next.js Streaming Explained: Faster Rendering vs CSR &amp; SSR</title>
      <dc:creator>Paweł Sobolewski</dc:creator>
      <pubDate>Wed, 15 Oct 2025 21:21:46 +0000</pubDate>
      <link>https://dev.to/u11d/nextjs-streaming-explained-faster-rendering-vs-csr-ssr-1369</link>
      <guid>https://dev.to/u11d/nextjs-streaming-explained-faster-rendering-vs-csr-ssr-1369</guid>
      <description>&lt;p&gt;Modern web apps need to load fast - users won’t wait for entire pages to render before engaging with content. Traditional methods like client-side rendering often introduce delays, especially when data fetching depends on large JavaScript bundles. &lt;a href="https://nextjs.org/docs/app/getting-started/fetching-data#streaming" rel="noopener noreferrer"&gt;&lt;strong&gt;Next.js streaming&lt;/strong&gt;&lt;/a&gt;, powered by React Server Components and Suspense, solves this by progressively sending page content to the browser as it becomes ready. The result: faster time-to-first-content and a smoother user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Streaming in Next.js?
&lt;/h2&gt;

&lt;p&gt;Streaming isn't just another performance optimization - it solves specific problems in modern frontend development. Users today demand immediate feedback, but traditional rendering approaches often create delays that make interfaces feel unresponsive.&lt;/p&gt;

&lt;p&gt;By allowing the server to send parts of a page to the browser as they become ready, streaming eliminates waiting for complete page rendering. Users can view and interact with meaningful content almost immediately. This approach not only enhances perceived performance but also eliminates the frustration of watching loading spinners or staring at empty placeholders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Imagine this scenario:&lt;/strong&gt; You have a large web page where most content is either static or quickly retrieved. However, one component depends on a slow external API. Without streaming, the entire page would be delayed while waiting for that single request. With streaming, the majority of the page appears immediately, with only the slower component arriving later. For users, this creates a fast, responsive experience, even when certain elements take longer to load.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js Streaming vs Client-Side Rendering (CSR)
&lt;/h2&gt;

&lt;p&gt;At first glance, streaming and client-side rendering seem to share a common goal: delivering content to users quickly without waiting for the entire page to load. However, they solve this problem in fundamentally different ways.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client-Side Rendering (CSR)
&lt;/h3&gt;

&lt;p&gt;With CSR, the server sends only a minimal HTML shell and a JavaScript bundle. Since &lt;strong&gt;client components cannot be asynchronous&lt;/strong&gt;, they can't effectively fetch data during rendering. Instead, developers must rely on &lt;a href="https://react.dev/reference/react/useEffect" rel="noopener noreferrer"&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/a&gt; for any asynchronous operations.&lt;/p&gt;

&lt;p&gt;This approach has three major drawbacks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Larger bundles&lt;/strong&gt; – more logic and components must be sent to the browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delayed data fetching&lt;/strong&gt; – network requests can only start &lt;em&gt;after&lt;/em&gt; the JavaScript has been downloaded, parsed, executed, and the component reaches the &lt;code&gt;useEffect&lt;/code&gt; stage. This significantly delays data retrieval compared to server-side methods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tricky security&lt;/strong&gt; - because data fetching happens on the client, sensitive information like API keys may need to be exposed or handled carefully.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Streaming
&lt;/h3&gt;

&lt;p&gt;Streaming takes the opposite approach. With rendering and data fetching happening on the server, the application can start retrieving data immediately. As soon as any part of the page is ready, it's sent to the browser and displayed - no need to wait for the entire UI. This approach reduces time to first meaningful paint and eliminates the "waterfall" effect common in CSR.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Next.js Streaming Works with React Server Components
&lt;/h2&gt;

&lt;p&gt;In Next.js, streaming leverages &lt;a href="https://react.dev/reference/rsc/server-components" rel="noopener noreferrer"&gt;&lt;strong&gt;React Server Components&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://react.dev/reference/react/Suspense" rel="noopener noreferrer"&gt;&lt;strong&gt;Suspense&lt;/strong&gt;&lt;/a&gt; to progressively send HTML to the browser instead of waiting for the entire page to render.&lt;/p&gt;

&lt;p&gt;Here's the process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initial render:&lt;/strong&gt; The server immediately sends HTML for ready-to-display elements (layout, header, placeholders, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suspense boundaries:&lt;/strong&gt; Components requiring slower data (API calls, database queries) are wrapped in special &lt;code&gt;&amp;lt;Suspense /&amp;gt;&lt;/code&gt; component, showing fallbacks like spinners or skeletons rather than blocking the entire page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progressive hydration:&lt;/strong&gt; Once data resolves, the server streams the completed HTML for that component, seamlessly replacing the fallback in the browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JS hydration (in parallel):&lt;/strong&gt; Simultaneously, client-side JavaScript gradually hydrates the page to make it fully interactive.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Using the React &lt;code&gt;use&lt;/code&gt; Hook for Streaming in Next.js
&lt;/h2&gt;

&lt;p&gt;Next.js also enables streaming through the &lt;a href="https://react.dev/reference/react/use" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;use&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; hook, which lets React components directly unwrap promises inside Client Components.&lt;/p&gt;

&lt;p&gt;The common implementation pattern works like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Server Component&lt;/strong&gt; initiates the async operation and passes the promise as a prop.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Client Component&lt;/strong&gt; utilizes the &lt;code&gt;use&lt;/code&gt; hook to consume the data, suspending itself until the data is ready.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why this matters:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;With traditional streaming, the streamed component must be a &lt;strong&gt;Server Component&lt;/strong&gt; that fetches data. Client Components, by default, cannot be asynchronous, which prevents them from directly participating in streaming.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;use&lt;/code&gt; hook solves this limitation: it enables &lt;strong&gt;Client Components&lt;/strong&gt; to consume promises and suspend. This means you can stream data &lt;strong&gt;and&lt;/strong&gt; immediately add interactivity (such as event handlers and UI state) without needing to split logic between server and client.&lt;/li&gt;
&lt;li&gt;This gives developers greater flexibility: data loading still begins early on the server, while the final rendering and interactive elements can reside in Client Components.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Does Next.js Streaming Require JavaScript?
&lt;/h2&gt;

&lt;p&gt;It's important to understand that &lt;strong&gt;streaming doesn't eliminate the need for JavaScript in the browser&lt;/strong&gt;. While the server handles data fetching and initial HTML rendering, the browser still needs JavaScript to replace temporary placeholders - like spinners or skeletons - with the actual content as it arrives.&lt;/p&gt;

&lt;p&gt;Without JavaScript, users would only see the static placeholders, preventing the progressive content delivery from functioning, even though the server has already generated this content.&lt;/p&gt;

&lt;p&gt;In essence, streaming speeds up content delivery, but JavaScript remains essential for swapping temporary elements with the final rendered components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js Streaming Example with Code (SSR vs CSR vs Streaming)
&lt;/h2&gt;

&lt;p&gt;Repository link: &lt;a href="https://github.com/u11d-com/blog_nextjs-streaming" rel="noopener noreferrer"&gt;https://github.com/u11d-com/blog_nextjs-streaming&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To demonstrate streaming benefits in a real-world context, I've built a very simple Next.js demo application that fetches and displays a list of funny jokes. This project compares three rendering strategies side by side: traditional Server-Side Rendering (SSR), Client-Side Rendering (CSR), and the newer React Server Components with streaming (with server and client components approaches).&lt;/p&gt;

&lt;p&gt;The application features separate pages for each rendering approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSR Page:&lt;/strong&gt; Renders everything on the server and delivers complete HTML in a single response. Users see content only after the server processes the entire page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSR Page:&lt;/strong&gt; Delivers a minimal HTML shell while JavaScript handles all data fetching on the client side. Users see loading states until data fetching and rendering complete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming Page:&lt;/strong&gt; Leverages React Server Components to progressively send UI parts to the browser as they become ready. This allows users to interact with visible content while slower components continue loading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming Page with &lt;code&gt;use&lt;/code&gt; Hook:&lt;/strong&gt; Uses the React &lt;code&gt;use&lt;/code&gt; hook to stream data directly into Client Components. This enables not only progressive rendering but also immediate interactivity, since Client Components can both consume async data and attach event handlers without waiting for a full page load.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application includes a built-in analytics system that tracks rendering times for each page section, helping visualize the performance differences between SSR, CSR, and streaming approaches.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Event&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;SSR (ms)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;CSR (ms)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;STREAMING (ms)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;STREAMING WITH USE (ms)&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fetching jokes started&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;281&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Joke list rendered&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2451&lt;/td&gt;
&lt;td&gt;2545&lt;/td&gt;
&lt;td&gt;2255&lt;/td&gt;
&lt;td&gt;2418&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Page rendered&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2722&lt;/td&gt;
&lt;td&gt;281&lt;/td&gt;
&lt;td&gt;272&lt;/td&gt;
&lt;td&gt;285&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can fetch and run the application Yourself, but let’s talk about results and what they mean.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next.js Performance Benchmark: SSR vs CSR vs Streaming
&lt;/h3&gt;

&lt;p&gt;Our benchmark clearly shows how each rendering strategy differs in data fetching timing and content delivery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSR (Server-Side Rendering)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fetching jokes started:&lt;/strong&gt; ~3 ms (almost immediately)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Joke list rendered:&lt;/strong&gt; ~2451 ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Page rendered:&lt;/strong&gt; ~2722 ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analysis:&lt;/strong&gt; While data fetching begins instantly, users see nothing until all data is processed. This creates a slower &lt;em&gt;first paint&lt;/em&gt;, despite the server's early work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSR (Client-Side Rendering)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fetching jokes started:&lt;/strong&gt; ~281 ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Page rendered:&lt;/strong&gt; ~281 ms (initial skeleton/spinner)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Joke list rendered:&lt;/strong&gt; ~2545 ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analysis:&lt;/strong&gt; With CSR, data fetching waits for JavaScript to load (~281 ms). Users see a placeholder quickly but wait over 2.5 seconds for actual content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Larger, more complex pages mean bigger JS bundles that take longer to execute. This delays data fetching even further, increasing time to meaningful content and hurting user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Streaming&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fetching jokes started:&lt;/strong&gt; ~4 ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Page rendered:&lt;/strong&gt; ~272 ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Joke list rendered:&lt;/strong&gt; ~2255 ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analysis:&lt;/strong&gt; Streaming offers the best experience: data fetching starts immediately, initial content appears in ~272 ms, and slower components load progressively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key advantage over CSR:&lt;/strong&gt; Streaming &lt;strong&gt;doesn't depend on JavaScript bundle size&lt;/strong&gt; to begin fetching data. This allows even complex pages to start loading meaningful content almost instantly, dramatically improving perceived performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Why Streaming is Best for Next.js Performance
&lt;/h2&gt;

&lt;p&gt;Comparing SSR, CSR, and Streaming in Next.js reveals distinct trade-offs for each approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSR&lt;/strong&gt; begins data fetching immediately on the server, but delivers a slower &lt;em&gt;time-to-first-content&lt;/em&gt; for users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSR&lt;/strong&gt; postpones data fetching until after JavaScript bundle execution, with larger pages further extending this delay - resulting in the longest wait for meaningful content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming&lt;/strong&gt; offers the best of both worlds: nearly instant data fetching, quick initial content rendering, and progressive component delivery. Because it doesn't depend on bundle size to start loading data, streaming ensures fast perceived performance even with complex pages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bottom line:&lt;/strong&gt; For modern Next.js applications where user experience and speed are priorities, streaming provides the most responsive and scalable solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ Section
&lt;/h2&gt;

&lt;p&gt;Frequently Asked Questions (FAQ) about Next.js Streaming&lt;/p&gt;

&lt;p&gt;Q: What is streaming in Next.js?&lt;/p&gt;

&lt;p&gt;A: Streaming is a rendering technique where the server sends parts of a page to the browser as soon as they’re ready. Instead of waiting for the entire page to render, users see meaningful content almost immediately, improving perceived performance.&lt;/p&gt;

&lt;p&gt;Q: How is streaming different from client-side rendering (CSR)?&lt;/p&gt;

&lt;p&gt;A: CSR waits until the JavaScript bundle loads before fetching data, delaying meaningful content. Streaming starts data fetching on the server instantly and progressively streams components, making the page feel faster and more responsive.&lt;/p&gt;

&lt;p&gt;Q: Does streaming replace SSR (Server-Side Rendering)?&lt;/p&gt;

&lt;p&gt;A: No. Streaming builds on SSR by adding progressive delivery. SSR sends a complete page after rendering, while streaming sends it in chunks, letting users see content earlier.&lt;/p&gt;

&lt;p&gt;Q: Do I still need JavaScript with streaming?&lt;/p&gt;

&lt;p&gt;A: Yes. While the server handles data fetching and initial HTML, JavaScript is required to replace placeholders with the actual streamed content and hydrate the UI for interactivity.&lt;/p&gt;

&lt;p&gt;Q: What is the use hook in streaming?&lt;/p&gt;

&lt;p&gt;A: The use hook allows React Client Components to directly consume promises. This means you can stream data into interactive Client Components without splitting logic between server and client.&lt;/p&gt;

&lt;p&gt;Q: When should I use streaming in my Next.js app?&lt;/p&gt;

&lt;p&gt;A: Use streaming when your page contains a mix of fast-loading and slow-loading content. It ensures users can interact with available content immediately while slower components continue to load in the background.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>performance</category>
      <category>react</category>
    </item>
    <item>
      <title>SSG, ISR, SSR, CSR: which strategy should I use in my Next.js e-commerce platform?</title>
      <dc:creator>Paweł Sobolewski</dc:creator>
      <pubDate>Mon, 29 Sep 2025 09:53:02 +0000</pubDate>
      <link>https://dev.to/u11d/ssg-isr-ssr-csr-which-strategy-should-i-use-in-my-nextjs-e-commerce-platform-4kjh</link>
      <guid>https://dev.to/u11d/ssg-isr-ssr-csr-which-strategy-should-i-use-in-my-nextjs-e-commerce-platform-4kjh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In today's evolving web development landscape, selecting the right rendering strategy is vital for creating fast, scalable, and user-friendly applications. &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;, a leading &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React&lt;/a&gt; framework, offers four powerful major rendering options: &lt;strong&gt;Static Site Generation&lt;/strong&gt; (SSG), &lt;strong&gt;Incremental Static Regeneration&lt;/strong&gt; (ISR), &lt;strong&gt;Server-Side Rendering&lt;/strong&gt; (SSR), and &lt;strong&gt;Client-Side Rendering&lt;/strong&gt; (CSR). Each approach comes with its own set of features and trade-offs.&lt;/p&gt;

&lt;p&gt;For e-commerce platforms, where performance, SEO, and content freshness directly impact business success, choosing the optimal rendering method is critical. This choice can dramatically affect page load speeds, search engine visibility, and—by extension—user satisfaction and conversion rates.&lt;/p&gt;

&lt;p&gt;With Next.js 13, the introduction of the &lt;strong&gt;App Router&lt;/strong&gt; brings a new routing paradigm centered on &lt;a href="https://nextjs.org/docs/app/getting-started/server-and-client-components" rel="noopener noreferrer"&gt;&lt;strong&gt;React Server Components&lt;/strong&gt;&lt;/a&gt;. This update offers enhanced flexibility and finer control over rendering strategies. While SSG, ISR, SSR, and CSR remain as core concepts, their implementation now relies primarily on caching behavior and component-level dynamic data fetching.&lt;/p&gt;

&lt;p&gt;In this article, we explore how &lt;strong&gt;SSG&lt;/strong&gt;, &lt;strong&gt;ISR&lt;/strong&gt;, &lt;strong&gt;SSR&lt;/strong&gt;, and &lt;strong&gt;CSR&lt;/strong&gt; function in &lt;strong&gt;Next.js 13&lt;/strong&gt; and later versions. We'll examine their strengths and limitations to help you make informed decisions when building or improving e-commerce platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Static Rendering vs Dynamic Rendering
&lt;/h2&gt;

&lt;p&gt;In Next.js, page rendering depends on &lt;strong&gt;when&lt;/strong&gt; and &lt;strong&gt;how&lt;/strong&gt; HTML is generated: either at build time (static) or at request time (dynamic). With the App Router, Next.js automatically selects the optimal rendering strategy based on how components fetch and handle data.&lt;/p&gt;

&lt;p&gt;By default, Next.js uses &lt;a href="https://nextjs.org/docs/app/getting-started/partial-prerendering#static-rendering" rel="noopener noreferrer"&gt;&lt;strong&gt;static rendering&lt;/strong&gt;&lt;/a&gt; when possible to maximize performance and scalability. For pages requiring fresh or user-specific data, it switches to &lt;a href="https://nextjs.org/docs/app/getting-started/partial-prerendering#dynamic-rendering" rel="noopener noreferrer"&gt;&lt;strong&gt;dynamic rendering&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ What triggers dynamic rendering?
&lt;/h3&gt;

&lt;p&gt;Next.js switches to dynamic rendering in these major cases:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;fetch()&lt;/code&gt; with &lt;code&gt;cache: 'no-store'&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Forces Server-Side Rendering (SSR) — no caching&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;fetch()&lt;/code&gt; with &lt;code&gt;next: { revalidate: 0 }&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Also disables caching — triggers SSR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;export const dynamic = 'force-dynamic'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Explicitly instructs Next.js to use SSR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use of dynamic functions like &lt;code&gt;cookies()&lt;/code&gt;, &lt;code&gt;headers()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Makes page request-specific — disables static rendering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use &lt;code&gt;params&lt;/code&gt; prop without &lt;code&gt;generateStaticParams()&lt;/code&gt; and proper &lt;code&gt;dynamicParams()&lt;/code&gt; settings&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&lt;a href="https://nextjs.org/docs/app/api-reference/functions/generate-static-params" rel="noopener noreferrer"&gt;generateStaticParams()&lt;/a&gt;&lt;/code&gt; allows pre-rendering of specific parameter values at build time, while remaining paths will be handled via SSR or return a 404, depending on the &lt;code&gt;&lt;a href="https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams" rel="noopener noreferrer"&gt;dynamicParams()&lt;/a&gt;&lt;/code&gt; configuration &lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  2. Static Site Generation (SSG)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Static Site Generation (SSG)&lt;/strong&gt; generates pages at build time and serves them as static HTML files. This approach delivers exceptionally fast load times, high reliability, and excellent scalability because content is prepared before any user requests and can be efficiently distributed through CDNs.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Key Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;⚡ &lt;strong&gt;Performance&lt;/strong&gt;: Pages load instantly from CDN or edge cache.&lt;/li&gt;
&lt;li&gt;🔒 &lt;strong&gt;Stability&lt;/strong&gt;: No server-side rendering needed, minimizing potential failures.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;SEO-ready&lt;/strong&gt;: Complete HTML available immediately for search engines.&lt;/li&gt;
&lt;li&gt;📈 &lt;strong&gt;Scalable&lt;/strong&gt;: Perfect for high-traffic pages due to pre-rendered content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚠️ Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Content stays static between builds, updates requires additional application build.&lt;/li&gt;
&lt;li&gt;Not ideal for pages needing real-time updates or personalization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given these advantages, ideal candidates for SSG in &lt;strong&gt;e-commerce&lt;/strong&gt; include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promotional or campaign landing pages,&lt;/li&gt;
&lt;li&gt;static marketing and brand content (e.g., about pages, policies, shipping info).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Product listing and details pages can also benefit from SSG when their content updates infrequently.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠️ Implementation
&lt;/h3&gt;

&lt;p&gt;Let's examine how to implement a static product details page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./ProductPage.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockProducts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;T-Shirt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Comfortable cotton t-shirt.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sneakers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lightweight running shoes.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Watch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elegant analog wristwatch.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Backpack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Durable everyday backpack.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sunglasses&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Polarized UV protection.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Stylish summer hat.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;7&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jacket&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Windproof outdoor jacket.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jeans&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Slim-fit denim jeans.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Scarf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Warm wool scarf.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Boots&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Waterproof hiking boots.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dynamicParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateStaticParams&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;mockProducts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockProducts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Since dynamicParams = false, this will never be rendered unless id is valid.&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;app/product/ssg/[id]/page.tsx&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🧠 Explanation
&lt;/h3&gt;

&lt;p&gt;In the example above, we use &lt;strong&gt;Static Site Generation (SSG)&lt;/strong&gt; to pre-render individual product pages at build time. Let's explore the key elements of the implementation:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;generateStaticParams()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This asynchronous function tells Next.js &lt;strong&gt;which dynamic routes to pre-render&lt;/strong&gt;. In our case, we hardcode 10 mock products, but it could be as well a call to Your database. Result would be the same: only these 10 product pages (e.g., &lt;code&gt;/product/ssg/1&lt;/code&gt;, &lt;code&gt;/product/ssg/2&lt;/code&gt;, ..., &lt;code&gt;/product/ssg/10&lt;/code&gt;) will be built statically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;server
├── app
│   ├── _not-found
│   └── favicon.ico
│   └── product
│          └── ssg
│               └── &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
│                    └── 1.html
│                    └── 2.html
│                    └── 3.html
│                    └── 4.html
│                    └── 5.html
│                    └── 6.html
│                    └── 7.html
│                    └── 8.html
│                    └── 9.html
│                    └── 10.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;dynamicParams = false&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By setting this flag, we &lt;strong&gt;explicitly instruct Next.js to return a 404 error for any route that wasn't generated&lt;/strong&gt; by &lt;code&gt;generateStaticParams()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/product/ssg/3&lt;/code&gt; → ✅ built at build time&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/product/ssg/999&lt;/code&gt; → ❌ will automatically render the 404 page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although we use the dynamic &lt;code&gt;params&lt;/code&gt; prop, pairing it with &lt;code&gt;generateStaticParams()&lt;/code&gt; enables complete SSG functionality — eliminating runtime rendering and the need for manual product validation in the component.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Incremental Static Regeneration (ISR)
&lt;/h2&gt;

&lt;p&gt;What if our static product pages need frequent updates—daily or weekly? This is where ISR comes into play.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/docs/app/guides/incremental-static-regeneration" rel="noopener noreferrer"&gt;&lt;strong&gt;Incremental Static Regeneration (ISR)&lt;/strong&gt;&lt;/a&gt; allows static pages to update in the background after deployment. It combines the performance benefits of Static Site Generation (SSG) with dynamic content updates—all without requiring a full rebuild.&lt;/p&gt;

&lt;p&gt;For e-commerce sites where product data changes regularly—such as prices, availability, or descriptions—ISR offers an ideal solution when updates are needed more frequently than full deployments allow.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❓How it works
&lt;/h3&gt;

&lt;p&gt;ISR generates pages at build time (like SSG), but includes a revalidation period. After this period expires, the next user request triggers a background regeneration. The new version is then cached and served to subsequent visitors.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Key Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;strong&gt;Hybrid flexibility&lt;/strong&gt;: Combines SSG benefits with content freshness.&lt;/li&gt;
&lt;li&gt;🔁 &lt;strong&gt;On-demand freshness&lt;/strong&gt;: Updates pages without full redeployment.&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Performance first&lt;/strong&gt;: Serves pre-rendered static content to most users.&lt;/li&gt;
&lt;li&gt;🔧 &lt;strong&gt;Control via revalidation&lt;/strong&gt;: Customisable content staleness thresholds.&lt;/li&gt;
&lt;li&gt;🛠️ &lt;strong&gt;Programmatic control&lt;/strong&gt;: Immediate page updates using &lt;a href="https://nextjs.org/docs/app/api-reference/functions/revalidatePath" rel="noopener noreferrer"&gt;&lt;code&gt;revalidatePath()&lt;/code&gt;&lt;/a&gt;—perfect for admin panels or CMS triggers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚠️ Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Slightly higher complexity compared to pure SSG.&lt;/li&gt;
&lt;li&gt;Regeneration occurs &lt;strong&gt;after&lt;/strong&gt; a stale page request.&lt;/li&gt;
&lt;li&gt;Revalidation cannot guarantee real-time consistency across all users.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🛠️ Implementation
&lt;/h3&gt;

&lt;p&gt;Let's modify our previous product details page to implement ISR with hourly updates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;notFound&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/navigation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./ProductPage.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockProducts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;T-Shirt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Comfortable cotton t-shirt.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sneakers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lightweight running shoes.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Watch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elegant analog wristwatch.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Backpack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Durable everyday backpack.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sunglasses&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Polarized UV protection.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Stylish summer hat.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;7&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jacket&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Windproof outdoor jacket.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jeans&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Slim-fit denim jeans.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Scarf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Warm wool scarf.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Boots&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Waterproof hiking boots.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateStaticParams&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;mockProducts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ISR configuration: revalidate every 1 hour&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;revalidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockProducts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;notFound&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;app/product/isr/[id]/page.tsx&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export const revalidate = 3600&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This line enables &lt;strong&gt;ISR&lt;/strong&gt; with a 1-hour (3,600 seconds) revalidation period. During this time, pages are served from cache. Once the period expires, the next user request triggers a background page regeneration.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;generateStaticParams()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As in the SSG example, we pre-generate pages for our 10 core products. These pages are built at build time, served as static HTML, and updated through ISR when needed.&lt;/p&gt;

&lt;p&gt;Removed &lt;code&gt;dynamicParams = false&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Unlike our SSG example where we used &lt;code&gt;dynamicParams = false&lt;/code&gt; to limit access to statically generated routes, this constraint is now removed. This means &lt;strong&gt;Next.js will attempt to render any route matching the dynamic pattern&lt;/strong&gt; (&lt;code&gt;/product/isr/[id]&lt;/code&gt;), regardless of whether it was included in &lt;code&gt;generateStaticParams()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This enables us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serve product pages for new items &lt;strong&gt;without rebuilding the app&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Dynamically generate pages for long-tail or user-generated content on demand.&lt;/li&gt;
&lt;li&gt;Return &lt;code&gt;404&lt;/code&gt; conditionally when a product ID doesn't exist in the data source.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This flexibility makes the route perfect for hybrid/static-dynamic behavior—the essence of ISR.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Server Side Rendering (SSR)
&lt;/h2&gt;

&lt;p&gt;So far, we've looked at &lt;strong&gt;Static Site Generation (SSG)&lt;/strong&gt; — where pages are pre-built during deployment — and &lt;strong&gt;Incremental Static Regeneration (ISR)&lt;/strong&gt;, which adds scheduled or on-demand revalidation on top of SSG.&lt;/p&gt;

&lt;p&gt;But what happens when your data changes constantly, depends on user authentication, or simply can't be predicted at build time?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server-Side Rendering (SSR)&lt;/strong&gt; is the answer.&lt;/p&gt;

&lt;p&gt;With SSR, pages are rendered on the server &lt;strong&gt;at request time&lt;/strong&gt; for each user visit. Rather than serving pre-rendered HTML from a cache, the server processes every incoming request individually, ensuring the data is always fresh.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Key Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🔄 &lt;strong&gt;Real-time data&lt;/strong&gt;: Fresh content is fetched for each request, eliminating stale data.&lt;/li&gt;
&lt;li&gt;👤 &lt;strong&gt;Personalization&lt;/strong&gt;: Perfect for user-specific content like account pages and dashboards.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;SEO optimization&lt;/strong&gt;: Search engines receive fully rendered HTML with the latest content.&lt;/li&gt;
&lt;li&gt;🔧 &lt;strong&gt;Dynamic control&lt;/strong&gt;: Data fetching happens on demand — without rebuilds or revalidation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚠️ Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🐢 &lt;strong&gt;Performance impact&lt;/strong&gt;: Pages load more slowly than SSG/ISR since HTML must be generated for each request.&lt;/li&gt;
&lt;li&gt;🧱 &lt;strong&gt;Scaling complexity&lt;/strong&gt;: High traffic can strain server resources and increase response times.&lt;/li&gt;
&lt;li&gt;💸 &lt;strong&gt;Higher costs&lt;/strong&gt;: Increased server processing leads to greater infrastructure expenses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🛠️ Implementation
&lt;/h3&gt;

&lt;p&gt;Let's now modify our previous product details page to implement SSR, which will dynamically render the page each time an user requests it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;notFound&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/navigation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./ProductPage.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockProducts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;T-Shirt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Comfortable cotton t-shirt.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sneakers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lightweight running shoes.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Watch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elegant analog wristwatch.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Backpack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Durable everyday backpack.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sunglasses&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Polarized UV protection.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Stylish summer hat.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;7&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jacket&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Windproof outdoor jacket.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jeans&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Slim-fit denim jeans.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Scarf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Warm wool scarf.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Boots&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Waterproof hiking boots.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockProducts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;notFound&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;app/product/ssr/[id]/page.tsx&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🧠 Explanation
&lt;/h3&gt;

&lt;p&gt;No &lt;code&gt;generateStaticParams()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Unlike &lt;strong&gt;SSG&lt;/strong&gt; and &lt;strong&gt;ISR&lt;/strong&gt;, this implementation doesn’t use &lt;code&gt;generateStaticParams()&lt;/code&gt; at all. The route is fully dynamic — there's no list of valid product IDs generated at build time.&lt;/p&gt;

&lt;p&gt;No &lt;code&gt;dynamicParams&lt;/code&gt; or &lt;code&gt;revalidate&lt;/code&gt; flags&lt;/p&gt;

&lt;p&gt;Since this page is rendered on every request, there’s no need to configure &lt;code&gt;dynamicParams&lt;/code&gt; or &lt;code&gt;revalidate&lt;/code&gt;. Each time the page is accessed, Next.js will evaluate the component on the server.&lt;/p&gt;

&lt;h1&gt;
  
  
  5. Client-Side Rendering (CSR)
&lt;/h1&gt;

&lt;p&gt;We've now covered &lt;strong&gt;Static Site Generation (SSG)&lt;/strong&gt;, &lt;strong&gt;Incremental Static Regeneration (ISR)&lt;/strong&gt;, and &lt;strong&gt;Server-Side Rendering (SSR)&lt;/strong&gt;—all involving server-side logic or pre-rendering. But there's one more model to explore: &lt;strong&gt;Client-Side Rendering (CSR)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With CSR, the server sends a minimal HTML shell and JavaScript bundle to the browser. The browser then renders the page content &lt;strong&gt;entirely on the client&lt;/strong&gt; by fetching data from an API or other source. This powers traditional Single Page Applications (SPAs) and remains a valid strategy in Next.js when used strategically.&lt;/p&gt;

&lt;p&gt;While Client-Side Rendering is fundamental to React development, it's &lt;strong&gt;generally not ideal as a default rendering strategy at the page level&lt;/strong&gt; in Next.js—particularly for content requiring strong SEO or fast initial visibility. Instead, CSR excels with &lt;strong&gt;specific, interactive components&lt;/strong&gt; like filters, carousels, modals, or client-specific widgets.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Key Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;strong&gt;Enhanced interactivity&lt;/strong&gt;: Perfect for dynamic, app-like experiences where user interaction is crucial.&lt;/li&gt;
&lt;li&gt;🧍 &lt;strong&gt;User-specific data&lt;/strong&gt;: Content personalizes directly in the browser without server-side processing.&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Seamless navigation&lt;/strong&gt;: Next.js' built-in routing and client caching enable instant page transitions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚠️ Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🐢 &lt;strong&gt;Slower initial load&lt;/strong&gt;: Users must wait for JavaScript to load and data fetching to complete before seeing content.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;SEO limitations&lt;/strong&gt;: Search engines may struggle to index client-rendered content, despite improvements in modern crawlers.&lt;/li&gt;
&lt;li&gt;🔌 &lt;strong&gt;JavaScript dependency&lt;/strong&gt;: The page becomes non-functional if JavaScript is disabled or fails to load.&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;Larger JS bundles&lt;/strong&gt;: Additional client-side logic increases bundle size, affecting performance on slower devices and networks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚠️ &lt;strong&gt;Important Note&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Even though Client Components run primarily in the browser, they are &lt;strong&gt;still pre-rendered on the server&lt;/strong&gt; during the initial request. Next.js uses this approach to deliver a minimal HTML shell, which improves initial load performance and perceived speed.&lt;/p&gt;

&lt;p&gt;After the HTML arrives, &lt;strong&gt;JavaScript "&lt;a href="https://react.dev/reference/react-dom/client/hydrateRoot" rel="noopener noreferrer"&gt;hydrates&lt;/a&gt;" the components on the client&lt;/strong&gt;, making them fully interactive.&lt;/p&gt;

&lt;p&gt;🧠 &lt;strong&gt;Be careful:&lt;/strong&gt; When server-rendered markup doesn't match client-side JavaScript during hydration, you may encounter &lt;strong&gt;hydration errors&lt;/strong&gt;. These errors can break your UI or trigger console warnings. Common causes include non-deterministic values (like &lt;code&gt;Date.now()&lt;/code&gt;, &lt;code&gt;Math.random()&lt;/code&gt;) or mismatched state between server and client.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠️ Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useParams&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/navigation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../ProductPage.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockProducts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;T-Shirt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Comfortable cotton t-shirt.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sneakers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lightweight running shoes.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Watch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elegant analog wristwatch.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Backpack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Durable everyday backpack.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sunglasses&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Polarized UV protection.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Stylish summer hat.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;7&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jacket&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Windproof outdoor jacket.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jeans&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Slim-fit denim jeans.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Scarf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Warm wool scarf.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Boots&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Waterproof hiking boots.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useParams&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProduct&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchProduct&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Simulate network delay&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockProducts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nf"&gt;setProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;fetchProduct&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loading-message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-not-found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;app/product/csr/[id]/page.tsx&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🧠 Explanation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;All logic is inside &lt;code&gt;useEffect()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unlike SSG, ISR, or SSR where data fetching happens on the server, in CSR &lt;strong&gt;everything happens on the client&lt;/strong&gt;, and all logic related to fetching product data is encapsulated inside a &lt;code&gt;useEffect()&lt;/code&gt; hook. This hook triggers after the component mounts and retrieves the necessary data based on the URL parameter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/docs/app/api-reference/directives/use-client" rel="noopener noreferrer"&gt;**&lt;code&gt;"use client"&lt;/code&gt;&lt;/a&gt; directive**&lt;/p&gt;

&lt;p&gt;This directive tells Next.js to treat the component as a client component, allowing hooks like &lt;strong&gt;useState&lt;/strong&gt;, &lt;strong&gt;useEffect&lt;/strong&gt; and &lt;strong&gt;useParams&lt;/strong&gt; to function properly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Route handling with &lt;code&gt;useParams()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of receiving &lt;code&gt;params&lt;/code&gt; from the server (like in SSG/SSR), the &lt;code&gt;id&lt;/code&gt; is pulled from the client-side router using &lt;code&gt;useParams()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom loading state&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As right now browser is not handling a loading state by itself (by loading the page content) there is a need to implement a custom one. To simulate real network latency &lt;code&gt;setTimeout&lt;/code&gt; delay has been used. This mimics how a real client would experience remote API requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧾 6. Summary: Choosing the Right Rendering Strategy in Next.js for E-commerce
&lt;/h2&gt;

&lt;p&gt;Next.js offers four &lt;strong&gt;major&lt;/strong&gt; powerful rendering strategies—Static Site Generation (&lt;strong&gt;SSG&lt;/strong&gt;), Incremental Static Regeneration (&lt;strong&gt;ISR&lt;/strong&gt;), Server-Side Rendering (&lt;strong&gt;SSR&lt;/strong&gt;) and Client-Side Rendering (&lt;strong&gt;CSR&lt;/strong&gt;). Each strategy has unique benefits, and choosing the right one for each route or component lets you optimize for performance, SEO, interactivity, and scalability.&lt;/p&gt;

&lt;p&gt;Here's how they compare:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Rendering Strategy&lt;/th&gt;
&lt;th&gt;Render Time&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SSG&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Build time&lt;/td&gt;
&lt;td&gt;Static pages, rarely updated product details&lt;/td&gt;
&lt;td&gt;
🔹 Fastest performance&lt;br&gt;
🔹 Great for SEO&lt;br&gt;
🔹 CDN-ready
&lt;/td&gt;
&lt;td&gt;
🔸 Requires rebuilds for updates&lt;br&gt;
🔸 Not suitable for live data
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ISR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Build + Revalidate&lt;/td&gt;
&lt;td&gt;Product pages updated periodically or on demand&lt;/td&gt;
&lt;td&gt;
🔹 Balance of freshness &amp;amp; speed&lt;br&gt;
🔹 Supports invalidation
&lt;/td&gt;
&lt;td&gt;
🔸 Slightly stale content possible&lt;br&gt;
🔸 More setup complexity
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SSR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per request&lt;/td&gt;
&lt;td&gt;Dynamic content, personalization, stock/pricing&lt;/td&gt;
&lt;td&gt;
🔹 Always up-to-date&lt;br&gt;
🔹 Supports user-specific logic
&lt;/td&gt;
&lt;td&gt;
🔸 Slower first load&lt;br&gt;
🔸 Requires server infrastructure
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CSR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Client-only&lt;/td&gt;
&lt;td&gt;Isolated, interactive components (e.g. cart)&lt;/td&gt;
&lt;td&gt;
🔹 Full interactivity&lt;br&gt;
🔹 Useful for client-only logic
&lt;/td&gt;
&lt;td&gt;
🔸 SEO limitations&lt;br&gt;
🔸 Slower initial render&lt;br&gt;
🔸 Larger JS bundle
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  🛒 E-commerce Use Case Recommendations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Landing pages, policies, info pages:&lt;/strong&gt; → ✅ &lt;strong&gt;SSG&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product listings/details with moderate updates:&lt;/strong&gt; → ✅ &lt;strong&gt;ISR&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product listings/details with frequent updates, personalized prices, live inventory, and A/B tests:&lt;/strong&gt; → ✅ &lt;strong&gt;SSR&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client-only interactions (cart, wishlist, filters):&lt;/strong&gt; → ✅ &lt;strong&gt;CSR&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔭 7. What’s Next?
&lt;/h2&gt;

&lt;p&gt;The rendering strategies discussed in this article — &lt;strong&gt;SSG, ISR, SSR, and CSR&lt;/strong&gt; — form the foundation of Next.js, particularly for e-commerce applications where performance and SEO are crucial.&lt;/p&gt;

&lt;p&gt;But this is just the beginning.&lt;/p&gt;

&lt;p&gt;In upcoming articles, we'll explore &lt;strong&gt;more advanced techniques&lt;/strong&gt; from recent Next.js versions, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Streaming and Suspense&lt;/strong&gt; for progressive rendering and better UX,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partial Prerendering (PPR)&lt;/strong&gt; to efficiently combine static and dynamic elements on the same page,&lt;/li&gt;
&lt;li&gt;Techniques to optimize &lt;strong&gt;per-component rendering strategies&lt;/strong&gt; in large-scale applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These approaches provide more precise control over performance and user experience—especially valuable for highly dynamic, personalized, and large-scale e-commerce platforms.&lt;/p&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why Next.js is one of the best solutions for E-commerce?</title>
      <dc:creator>Paweł Sobolewski</dc:creator>
      <pubDate>Tue, 01 Jul 2025 08:43:05 +0000</pubDate>
      <link>https://dev.to/u11d/why-nextjs-is-one-of-the-best-solutions-for-e-commerce-178c</link>
      <guid>https://dev.to/u11d/why-nextjs-is-one-of-the-best-solutions-for-e-commerce-178c</guid>
      <description>&lt;p&gt;In the constantly changing world of web development, e-commerce poses a unique set of challenges: complex product data, dynamic content, SEO demands, fast page loads, secure checkout flows, integration with multiple external systems and many, many more.&lt;/p&gt;

&lt;p&gt;As developers, we’re constantly looking for tools that help us deliver all of this without compromising on performance or maintainability. &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; delivers on all fronts — and then some more.&lt;/p&gt;

&lt;p&gt;If you’re evaluating tech stacks for your next e-commerce project, here’s why Next.js deserves a spot at the top of your list.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Performance by Design
&lt;/h2&gt;

&lt;p&gt;E-commerce websites live and die by performance. According to &lt;a href="https://www.thinkwithgoogle.com/marketing-strategies/app-and-mobile/mobile-page-speed-conversion-data/" rel="noopener noreferrer"&gt;Google&lt;/a&gt;, even a one-second delay in page load time can reduce conversions by up to 20%. Next.js addresses this head-on by giving you multiple &lt;a href="https://nextjs.org/docs/app/building-your-application/rendering" rel="noopener noreferrer"&gt;rendering strategies&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Static Site Generation (SSG)&lt;/li&gt;
&lt;li&gt;Server-Side Rendering (SSR)&lt;/li&gt;
&lt;li&gt;Client Side Rendering (CSR)&lt;/li&gt;
&lt;li&gt;Incremental Static Regeneration (ISR)&lt;/li&gt;
&lt;li&gt;Partial Prerendering (PPR, currently experimental)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This per-route rendering flexibility lets you optimize each part of your store — from blazing-fast landing pages to real-time personalized carts.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Built-in SEO Superpowers
&lt;/h2&gt;

&lt;p&gt;Next.js delivers server-rendered HTML out of the box, making sure search engines like Google can immediately crawl meaningful content. For developers, this translates to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full control of metadata with &lt;strong&gt;next/head&lt;/strong&gt;, &lt;strong&gt;metadata&lt;/strong&gt; object or even dynamic content with &lt;strong&gt;generateMetadata&lt;/strong&gt; function&lt;/li&gt;
&lt;li&gt;SEO-friendly dynamic routing&lt;/li&gt;
&lt;li&gt;Easily integrated structured data for rich search snippets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When search engines properly index your category and product pages, you'll see a natural boost in organic traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Smart Data Caching and Request Management for Better Performance
&lt;/h2&gt;

&lt;p&gt;In e-commerce, caching goes beyond storing page content. A major performance boost comes from &lt;strong&gt;efficient data fetching and preventing duplicate requests&lt;/strong&gt; — crucial when handling large product catalogs, filtering systems, and personalized content.&lt;/p&gt;

&lt;p&gt;Next.js provides complete control over &lt;strong&gt;data-layer &lt;a href="https://nextjs.org/docs/app/deep-dive/caching" rel="noopener noreferrer"&gt;caching&lt;/a&gt;&lt;/strong&gt;, from server to edge computing. Better yet, it works out of the box without any custom configuration, thanks to its extended node &lt;a href="https://nodejs.org/en/learn/getting-started/fetch" rel="noopener noreferrer"&gt;&lt;strong&gt;fetch&lt;/strong&gt;&lt;/a&gt; utility.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Request Memoization&lt;/strong&gt; - During server-side rendering, Next.js stores responses received via the &lt;strong&gt;fetch&lt;/strong&gt; API. This means that regardless of where and how many times you request the same data in &lt;a href="https://react.dev/reference/rsc/server-components" rel="noopener noreferrer"&gt;&lt;strong&gt;React Server Components (RSC)&lt;/strong&gt;&lt;/a&gt;, the actual request occurs only once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Cache&lt;/strong&gt; - Need persistent data across multiple page renders, sessions, and users? Next.js provides this functionality out of the box by storing responses in deployed application memory in a controlled way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full Route Cache&lt;/strong&gt; - By caching renderable pages generated through SSG, ISR, or forced caching, Next.js can deliver content to end users at blazing speeds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Router Cache&lt;/strong&gt; - Thanks to Next.js's ability to utilize both server and client environments, subsequent client-side navigations can be stored and reused within a single user session to display previously visible content immediately.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Streaming in Next.js: Faster Renders, Better UX, and SEO Gains
&lt;/h2&gt;

&lt;p&gt;With the App Router and React Server Components, &lt;strong&gt;Next.js supports HTTP streaming&lt;/strong&gt;, which allows the server to send HTML to the browser incrementally. Instead of waiting for the entire page to generate, content appears as soon as each part of the UI is ready.&lt;/p&gt;

&lt;p&gt;This approach delivers significant performance and user experience benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time to First Byte (TTFB):&lt;/strong&gt; The server begins sending content instantly, reducing initial load time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Largest Contentful Paint (LCP):&lt;/strong&gt; Essential elements like product titles, images, and prices appear early, with secondary components streaming in afterward.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perceived performance:&lt;/strong&gt; Users see content faster, creating a more responsive experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the &lt;strong&gt;SEO side&lt;/strong&gt;, streaming offers two key advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search engine bots can begin parsing HTML immediately through the open connection, continuously receiving the page's complete structure.&lt;/li&gt;
&lt;li&gt;The streamed content remains &lt;strong&gt;server-rendered HTML&lt;/strong&gt; rather than client-side JS, ensuring all content—including personalized and dynamic elements—stays crawlable and indexable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This delivers the &lt;strong&gt;best of both worlds&lt;/strong&gt;: rapid initial loads &lt;em&gt;and&lt;/em&gt; complete SEO visibility, regardless of page complexity or personalization.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Multiple Layouts for Complex E-commerce Experiences
&lt;/h2&gt;

&lt;p&gt;Modern e-commerce sites need various specialized layouts beyond basic shop pages, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Marketing landing pages&lt;/li&gt;
&lt;li&gt;Product listings and product detail pages (PDPs)&lt;/li&gt;
&lt;li&gt;Checkout and cart interfaces&lt;/li&gt;
&lt;li&gt;User dashboards for orders and subscriptions&lt;/li&gt;
&lt;li&gt;Admin and vendor portals&lt;/li&gt;
&lt;li&gt;Blog and content sections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next.js supports &lt;strong&gt;multiple layouts&lt;/strong&gt; out of the box - a significant advantage for e-commerce projects with diverse page types. You can define distinct layouts for different pages while maintaining shared elements like navigation and cart state across views. This approach keeps your code organized and helps scale a complex store into a modular, app-like experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Integrating Next.js with Advanced Backends like Medusa
&lt;/h2&gt;

&lt;p&gt;For developers building &lt;strong&gt;fully customizable commerce systems&lt;/strong&gt;, frameworks like &lt;a href="https://medusajs.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Medusa&lt;/strong&gt;&lt;/a&gt; have gained significant popularity. Medusa offers a modular, open-source backend that provides plug-and-play services for products, carts, orders, payments, and more.&lt;/p&gt;

&lt;p&gt;Next.js pairs exceptionally well with platforms like Medusa for several reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It seamlessly integrates with Medusa's REST API,&lt;/li&gt;
&lt;li&gt;You can leverage &lt;a href="https://nextjs.org/docs/pages/building-your-application/routing/api-routes" rel="noopener noreferrer"&gt;&lt;strong&gt;Next.js API routes&lt;/strong&gt;&lt;/a&gt; as middleware between Medusa and the frontend (for authentication or webhook handling),&lt;/li&gt;
&lt;li&gt;Medusa's modular services (inventory, discounts, fulfillment) align perfectly with Next.js's page-level rendering logic,&lt;/li&gt;
&lt;li&gt;When combined with &lt;strong&gt;ISR and caching&lt;/strong&gt;, you can scale dynamic product catalogs while maintaining peak performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simply put, Medusa manages your backend business logic while Next.js provides complete control over the customer-facing experience — maintaining a clean separation of concerns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Whether you're launching a new storefront or modernizing an existing one, Next.js delivers the performance, flexibility, and future-ready architecture that modern e-commerce platforms demand. It empowers teams to create lightning-fast shopping experiences, boost SEO performance, and integrate seamlessly with both legacy systems and modern headless commerce platforms.&lt;/p&gt;

&lt;p&gt;Next.js provides a robust foundation for building exceptional digital retail experiences that serve both current needs and future growth. Its capabilities enhance user experience while supporting sustainable, long-term development.&lt;/p&gt;

&lt;p&gt;Stay tuned for upcoming articles that will explore these topics in depth, complete with practical examples and real-world use cases.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
