Teachnique
      CourseRoadmaps
      Login

      Introduction

      Project SetupCLI

      IntroductionAPP RouterTemplateLoading UIError Handling404 Page

      Linking and Navigating

      Dynamic RoutesRoute groupsParallel RoutesIntercepting Routes

      Route handlersCacheCommon Questions

      Middleware

      CSRSSR & SSGISR

      React Server ComponentsServer-Side Rendering

      SuspenseStreaming

      Server & Client ComponentServer vs. Client ComponentBest Practices

      Server-Side Rendering Strategies

      Data Fetching & Caching & RedirectThird-Party Request Libraries on the Server SideBest Practices

      Request MemoizationData CacheFull Route CacheRouter Cache

      Server Actions IFormServer Actions IIOptimistic Update

      Tailwind CSSCSS-in-JSSass

      Environment VariablesAbsolute Imports& Module Path AliasesRoute Segment Config

      Image & LCPImage IImage IIOptimizing IOptimizing II

      Next FontFont ParameterApply Styles

      Feedback

      Submit request if you have any questions.

      Course
      Server vs. Client Component

      Next.js Mastery: From Fundamentals to Full-Stack

      Unlock the power of Next.js with this comprehensive course! Starting with the basics, you’ll learn essential skills such as routing, data fetching, and styling. Progress through practical projects, including building your own React Notes app, to gain hands-on experience. Dive into the source code to understand the inner workings and core principles of Next.js. Perfect for developers with a basic knowledge of React and Node.js, this course ensures you’ll be ready to create high-performance full-stack applications efficiently. Join us and master Next.js, backed by industry experts and a supportive learning community.

      Server Components vs. Client Components

      How to Choose?

      If you need to...
      Server Components
      Client Components
      Fetch data
      ✅
      ❌
      Access backend resources directly
      ✅
      ❌
      Keep sensitive information on the server (e.g., access tokens, API keys)
      ✅
      ❌
      Use dependencies on the server to reduce client-side JavaScript size
      ✅
      ❌
      Add interactivity and event listeners (e.g., onClick(), onChange())
      ❌
      ✅
      Use state and lifecycle methods (e.g., useState(), useReducer(), useEffect())
      ❌
      ✅
      Use browser-specific APIs
      ❌
      ✅
      Use custom hooks that rely on state, effects, or browser-specific APIs
      ❌
      ✅
      Use React class components
      ❌
      ✅

      Rendering Environment

      Server components are only rendered on the server, while client components are rendered on the server once and then on the client.
      What does this mean? Let's write an example:
      Create app/client/page.js:
      'use client'
      
      import { useState } from 'react';
      
      console.log('client')
      
      export default function Page() {
      console.log('client Page')
      
      const [text, setText] = useState('init text');
      
      return (
      <button onClick={() => {
      setText('change text')
      }}>{text}</button>
      )
      }
      Create app/server/page.js:
      javascriptCopy codeconsole.log('server')
      
      export default function Page() {
      console.log('server Page')
      
      return (
      <button>button</button>
      )
      }
      Now, when you run npm run build, what will be printed?
      The answer is that both client components and server components will print:
      
      
      And based on the output, both /client and /server use static rendering.
      When running npm run start, what will be printed?
      The answer is nothing will be printed in the command line. When accessing /client, the browser will print:
      client page-4b10cfcd1c67a6d6.js:1
      
      client Page page-4b10cfcdic67a6d6.js:1
      When accessing /server, the browser will not print anything:
      
      
      The client component prints in the browser because it runs on the client side. But why does the client component also run once during the build? Let's check the /client response:
      
      
      You will see that init text comes from the useState value, but it still appears in the HTML. This is the purpose of compiling the client component, to quickly display content on the initial load.
      So, server components and client components don't correspond directly to physical servers and clients. Server components run at build time and on the server, while client components run at build time, on the server (to generate initial HTML), and on the client (to manage the DOM).

      Alternating Between Server and Client Components

      In actual development, it's unlikely to use purely server or client components. When alternating between them, remember:
      Server components can directly import client components, but client components cannot import server components.
      'use client'
      
      // This is not allowed
      import ServerComponent from './Server-Component'
      
      export default function ClientComponent({ children }) {
      const [count, setCount] = useState(0)
      
      return (
      <>
      <button onClick={() => setCount(count + 1)}>{count}</button>
      <ServerComponent />
      </>
      )
      }
      
      As mentioned when introducing client components:
      "use client" declares the boundary between server and client component modules. When defined in a file, all imported modules, including child components, are considered part of the client bundle.
      
      The default is server components, but when imported into client components, they are considered client components. The rule that client components cannot import server components is to ensure that if you use Node APIs in a server component, it won't be imported into a client component.
      However, you can pass server components as props to client components:
      'use client'
      
      import { useState } from 'react'
      
      export default function ClientComponent({ children }) {
      const [count, setCount] = useState(0)
      
      return (
      <>
      <button onClick={() => setCount(count + 1)}>{count}</button>
      {children}
      </>
      )
      }
      import ClientComponent from './client-component'
      import ServerComponent from './server-component'
      
      export default function Page() {
      return (
      <ClientComponent>
      <ServerComponent />
      </ClientComponent>
      )
      }
      This way, <ClientComponent> and <ServerComponent> are decoupled and rendered independently.
      Note: You might wonder why you should bother using ServerComponent. This is because ServerComponent has many benefits, such as not being bundled into the client bundle. Why is it okay to pass it as props? We will explain this more concretely in the practical project "React Notes | Note Search".

      Component Rendering Principles

      On the server side:
      Next.js uses React APIs to orchestrate rendering. The rendering work is divided into chunks based on routes and Suspense, and each chunk is rendered in two steps:
      1. React renders server components into a special data format called React Server Component Payload (RSC Payload).
      2. Next.js uses the RSC Payload and client component code to render HTML on the server.
      The RSC Payload contains the following information:
      1. The rendered results of server components.
      1. Placeholders and reference files for client components.
      1. Data passed from server components to client components.
      On the client side:
      1. Load the rendered HTML to quickly display a non-interactive UI.
      2. The RSC Payload is used to reconcile the client and server component trees and update the DOM.
      3. JavaScript code is used to hydrate client components, making the application interactive.
      
      
      Note: The diagram above describes the initial page load process. SC represents Server Components, and CC represents Client Components.
      
      In the previous section, we discussed that Suspense and Streaming still have some issues, such as the need to load the same amount of JavaScript and the requirement to hydrate all components, even those that don't need hydration.
      Using server components and client components can solve these problems. Server component code is not bundled into the client bundle. When rendering, only client components need to be hydrated, not server components.
      During subsequent navigation:
      1. Client components are fully rendered on the client.
      2. React uses the RSC Payload to reconcile the client and server component trees and update the DOM.
      
      
      View Code and Demo Online: CodeSandbox Server Components and Client Components