
Kiến trúc phần mềm
Hiểu ranh giới Server và Client Components trong Next.js để giảm JavaScript phía browser mà vẫn giữ trải nghiệm tương tác.
Một dòng "use client" đặt sai chỗ có thể biến lợi thế lớn nhất của Next.js thành một React SPA nặng hơn bình thường.
Đó không có nghĩa là "use client" là xấu. Vấn đề là nhiều người dùng nó như một cách sửa nhanh khi component cần state, event handler hoặc browser API. Nếu đặt directive này ở page.tsx, layout.tsx hoặc một component cha quá lớn, bạn đang mở rộng ranh giới client nhiều hơn cần thiết.
Trong App Router, component là Server Component mặc định. Chúng có thể lấy dữ liệu ở server và dùng dependency chỉ dành cho server mà không gửi code đó xuống browser. Khi một file có "use client", file đó và các dependency được import trực tiếp bên dưới nó trở thành một phần của client-side graph.
Một trang sản phẩm có title, dữ liệu, mô tả dài và bộ lọc tìm kiếm. Vì bộ lọc cần useState, cách dễ nhất có vẻ là biến toàn bộ page thành Client Component.
"use client";
export default function ProductsPage() {
const [query, setQuery] = useState("");
return (
<>
<SearchFilters query={query} onQueryChange={setQuery} />
<ProductGrid query={query} />
</>
);
}Cách này hoạt động, nhưng page giờ đã là client boundary. Những phần vốn không cần tương tác—như layout, nội dung, formatter hoặc product grid—dễ bị kéo về phía browser hơn mức cần thiết.
Giữ page và dữ liệu ở server. Chỉ tách phần thật sự cần browser thành Client Component. Bộ lọc vẫn tương tác ở browser, nhưng product grid, dữ liệu và phần nội dung còn lại vẫn được render ở server.
export default async function ProductsPage({ searchParams }) {
const products = await getProducts(searchParams.query);
return (
<>
<SearchFilters />
<ProductGrid products={products} />
</>
);
}"use client";
export function SearchFilters() {
// state, event handlers and URL interaction live here
}Use client không đánh dấu một component có tương tác. Nó đánh dấu ranh giới nơi browser bắt đầu phải tham gia.
Dashboard realtime, rich text editor, drag-and-drop board hoặc công cụ nội bộ có client state phức tạp sẽ cần nhiều Client Component hơn. Mục tiêu không phải đưa mọi thứ về server; mục tiêu là giữ JavaScript phía client ở đúng nơi nó tạo ra giá trị.
Next.js mạnh không phải vì mọi thứ tự động chạy nhanh. Nó mạnh khi đội ngũ biết phần nào cần server, phần nào cần browser, và không để một interactive button kéo cả page sang client. Trước khi thêm use client, hãy hỏi: phần này có thật sự cần chạy trong browser, hay chỉ đang nằm gần một phần cần chạy trong browser?