Mục lục

Next.js App Router: Server vs Client Boundary

Làm chủ ranh giới giữa Server và Client Components để tối ưu hóa SEO và Core Web Vitals.

Sự ra đời của React Server Components (RSC) trong Next.js App Router đã thay đổi hoàn toàn cách chúng ta tư duy về ứng dụng web. Một trong những sai lầm lớn nhất là không xác định rõ "Ranh giới" (Boundary).

1. Triết lý "Server-First"

Trong Next.js, mặc định mọi component đều là Server Component.

Điều gì xảy ra khi bạn dùng sai?

Nếu bạn fetch data trong Client Component ("use client") bằng useEffect, bạn đang:

  1. Gây ra "Layout Shift" hoặc hiển thị Loading Skeleton lâu hơn.
  2. Tăng kích thước JS bundle gửi xuống trình duyệt.
  3. Làm hỏng khả năng SEO của nội dung đó.

Giải pháp: Async Server Components

Fetch data trực tiếp tại nguồn (Server).

tsx:
// app/posts/page.tsx
export default async function Page() {
  const posts = await getPosts(); // Fetch cực nhanh nội bộ server
  
  return (
    <ul>
      {posts.map(post => <li key={post.id}>{post.title}</li>)}
    </ul>
  );
}

2. Khi nào thực sự cần "use client"?

Đừng sợ dùng use client, nhưng hãy dùng đúng lúc:

  • Khi cần useState, useReducer, useEffect.
  • Khi dùng các Browser APIs (window, localStorage).
  • Khi xử lý Event Listeners (onClick, onChange).

Mẹo chuyên gia: "The Don't Boundary"

Đừng bao giờ import Server Component vào Client Component một cách trực tiếp.

Sai:

tsx:
"use client";
import MyServerComponent from './ServerComp'; // Lỗi hoặc bị ép thành client component

Đúng: Dùng Composition

tsx:
"use client";
export default function MyClientComponent({ children }) {
  return <div onClick={() => ...}>{children}</div>; // children có thể là Server Component
}

3. Good Practice: Tối ưu hóa Context

Đừng bọc toàn bộ App trong một Provider khổng lồ nếu không cần thiết.

Bad

tsx:
// layout.tsx
<AuthProvider>
  <ThemeProvider>
    <QueryProvider>
      {children} {/* Toàn bộ ứng dụng bị "khóa" vào Client-side rendering tree */}
    </QueryProvider>
  </ThemeProvider>
</AuthProvider>

Good

Tạo các Providers riêng biệt và bọc sát nơi sử dụng, hoặc đảm bảo các Providers đó chỉ chứa logic tối giản.


Bài tập: Phân tích thất bại

Hãy nhìn vào dự án hiện tại của bạn, tìm một component đang dùng "use client" và thử gỡ bỏ nó bằng cách chuyển logic xử lý data lên cha (Server Component). Bạn sẽ thấy tốc độ tải trang (LCP) cải thiện đáng kể.

Quảng cáo
mdhorizontal