Điểm SEO 71/100 chưa đạt yêu cầu, cần được trên 80 điểm
Nếu như chỉ quen thuộc với ReactJS, hẳn bạn sẽ khá lạ lẫm khi nghe tới hai khái niệm Server Component và Client Component của Next.js.
Trong bài viết này, chúng ta sẽ cùng nhau khám phá về công dụng, cách hoạt động cũng như khi nào cần sử dụng hai loại component này trong dự án Next.js.
1. Khái niệm
1.1. Server Components
Server Components là các component React chỉ chạy hoàn toàn trên server. Server Component là component mặc định của NextJs kể từ phiên bản 13 với App Router
1.2. Client Components
Là các component tương tự component trong React truyền thống, được render trực tiếp trên trình duyệt Client. Để biến một Server Component thành Client Component, ta cần cho NextJs biết bằng cách thêm ‘use client’
vào đầu
2. Cách thức hoạt động của Server, Client Component
Để hiểu rõ cách thức hoạt động của hai loại component này. Ta cùng tìm hiểu và phân tích sơ đồ hoạt động sau

Bước 1: User Request
Hành động: Mọi thứ bắt đầu khi người dùng thực hiện một hành động trong Client Browser, chẳng hạn như gõ một URL vào thanh địa chỉ hoặc nhấp vào một thẻ <Link>
.
Kết quả: Một HTTP Request được gửi từ trình duyệt đến Next.js Server.
Bước 2: Router xử lý (App Router)
Hành động: Next.js Server nhận được yêu cầu. App Router sẽ phân tích URL (ví dụ: /products/123) để xác định component nào cần được render cho route đó
(ví dụ: file app/products/[id]/page.js).
Bước 3: Fetch Data
Hành động: Đây là một trong những bước quan trọng nhất của Server Components. Server Component, vì đang chạy hoàn toàn trên server, có thể truy cập trực tiếp và an toàn vào các nguồn dữ liệu (Data Sources).
Ví dụ: Nó có thể gọi thẳng đến Database, các External APIs, hoặc đọc file từ File System bằng cách sử dụng async/await.
Lợi ích: Các thông tin nhạy cảm như chuỗi kết nối database, API keys không bao giờ bị gửi về trình duyệt.
Kết quả: Dữ liệu được trả về (Return Data) cho Server Component để xử lý ở bước tiếp theo.
Bước 4: Tạo RSC Payload
Hành động: Sau khi có dữ liệu, Server Component thực hiện các công việc chính của nó:
- Chạy trên server: Toàn bộ logic được thực thi trên máy chủ.
- Không có JavaScript ở client: Mã nguồn của component này không được đóng gói để gửi về trình duyệt.
Kết quả: Server Component KHÔNG render ra HTML trực tiếp. Thay vào đó, nó tạo ra một định dạng dữ liệu đặc biệt gọi là RSC Payload (Serialized React Element Tree). Đây là một “bản mô tả” cây giao diện dưới dạng text, rất gọn nhẹ. Nó chứa:
- Cấu trúc UI của Server Component.
- Các placeholders chỉ định vị trí của các Client Components sẽ được chèn vào.
Bước 5: HTML Generation
Hành động: Next.js trên server lấy RSC Payload đã được tạo ở bước 4 và sử dụng nó để tạo ra file HTML cuối cùng.
- Trong quá trình này, các Client Components cũng được render lần đầu trên server (Server-Side Rendering – SSR) để tạo ra HTML tĩnh ban đầu. Điều này đảm bảo người dùng thấy giao diện ngay lập tức.
- Streaming support: Next.js có thể gửi HTML theo từng phần (stream) về trình duyệt, giúp trang hiển thị nhanh hơn thay vì phải chờ toàn bộ trang render xong.
Bước 6: Trả về Client (HTTP Response)
Hành động: Server gửi một HTTP Response về cho trình duyệt. Gói phản hồi này chứa:
- HTML content: Toàn bộ HTML của trang.
- Client-side JavaScript bundle: Chỉ là các file JS của những Client Component được sử dụng trên trang.
Kết quả cuối cùng:
- Trình duyệt nhận HTML và hiển thị nó ngay lập tức.
- Sau đó, nó tải và thực thi các file JavaScript.
- Quá trình Hydration diễn ra: Trình duyệt gắn các state và sự kiện (onClick, onChange) vào các Client Component được gửi tới, khiến chúng có thể tương tác.
3. Sử dụng Server, Client Component khi nào?
Trường hợp | Server Component | Client Component |
---|---|---|
Lấy dữ liệu tĩnh | ✅ | ❌ |
Cần tương tác | ❌ | ✅ |
Cập nhật trực tiếp (Chat, Thông báo, …) | ❌ | ✅ |
Dữ liệu cần bảo mật | ✅ | ❌ |
Browser APIs (localStorage, geolocation, …) | ❌ | ✅ |
Component chỉ hiển thị, không có tương tác | ✅ | ❌ |
Sử dụng thư viện chỉ chạy ở trình duyệt (Zustand, Redux, …) | ❌ | ✅ |
4. Ví dụ trực quan
Ví dụ, Component Page
là Server Component có chức năng lấy dữ liệu về bài đăng và truyền dữ liệu đó dưới dạng props cho LikeButton
để xử lý tương tác phía Client.
//app/[id]/page.tsx
import LikeButton from '@/app/ui/like-button'
import { getPost } from '@/lib/data'
export default async function Page({ params }: { params: { id: string } }) {
const post = await getPost(params.id)
return (
<div>
<main>
<h1>{post.title}</h1>
{/* ... */}
<LikeButton likes={post.likes} />
</main>
</div>
)
}
//app/ui/like-button.tsx
'use client'
import { useState } from 'react'
export default function LikeButton({ likes }: { likes: number }) {
// ...
}