Giới thiệu vấn đề Data Fetching trong Next.js
Trong các dự án Next.js, việc lấy dữ liệu (data fetching) ảnh hưởng trực tiếp tới tốc độ tải trang, SEO và trải nghiệm người dùng. Next.js cung cấp nhiều phương pháp: getStaticProps, getServerSideProps, Server Components và fetch trong các route handler. Tuy nhiên, khi dự án mở rộng, việc lựa chọn sai phương pháp có thể gây lãng phí tài nguyên và giảm hiệu năng.
So sánh các phương pháp truyền thống
1. getStaticProps (Static Generation)
Được chạy tại thời điểm build, tạo HTML tĩnh cho mỗi trang. Thích hợp cho nội dung không thay đổi thường xuyên. Khi dữ liệu cần cập nhật, phải dùng revalidate để kích hoạt Incremental Static Regeneration (ISR).
2. getServerSideProps (Server‑Side Rendering)
Chạy trên server mỗi khi có yêu cầu. Đảm bảo dữ liệu luôn mới, nhưng tăng thời gian phản hồi vì phải thực hiện truy vấn mỗi lần.
Server Components – Đột phá trong việc giảm tải client
Server Components cho phép viết React component chạy hoàn toàn trên server, trả về HTML đã được render sẵn. Nhờ đó, client không cần tải JavaScript cho các phần không tương tác, giảm kích thước bundle và thời gian tải.
Dưới đây là ví dụ một Server Component lấy danh sách bài viết từ API nội bộ:
<!-- components/PostList.server.jsx -->
<script>"use client";</script>
import React from "react";
export default async function PostList() {
const res = await fetch("https://api.example.com/posts", {
next: { revalidate: 60 } // ISR mỗi 60 giây
});
const posts = await res.json();
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
Ở ví dụ trên, fetch được gọi trên server, trả về HTML tĩnh và được cache trong 60 giây. Khi người dùng truy cập, họ nhận được danh sách đã được render sẵn mà không cần tải thêm JavaScript.
Kết hợp ISR và Server Components để tối ưu hiệu năng
Đối với trang có phần tĩnh (SEO‑friendly) và phần động (cập nhật thường xuyên), ta có thể tách thành:
- Header và meta thông tin: sử dụng
getStaticPropsvớirevalidateđể tạo HTML tĩnh. - Danh sách nội dung: triển khai bằng Server Component như trên, với
next: { revalidate: X }để tự động làm mới.
Điều này giúp giảm thời gian phản hồi ban đầu (do phần tĩnh được phục vụ nhanh) đồng thời vẫn duy trì dữ liệu mới nhất cho phần nội dung.
Thực hành: Tối ưu một trang blog
Giả sử chúng ta có một trang /blog hiển thị danh sách bài viết. Đầu tiên, tạo file app/blog/page.jsx:
<!-- app/blog/page.jsx -->
import Header from "@/components/Header";
import PostList from "@/components/PostList.server";
export const revalidate = 300; // ISR cho toàn trang mỗi 5 phút
export default function BlogPage() {
return (
<>
<Header title="Blog" />
<PostList />
</>
);
}
Trong đó, Header là một Client Component chứa navigation và các hook UI, còn PostList là Server Component đã mô tả ở trên. Khi người dùng truy cập /blog, Next.js sẽ:
- Render
Headertrên client (nhỏ gọn). - Render
PostListtrên server, cache kết quả trong 60 giây. - Cache toàn bộ trang trong 300 giây nhờ
revalidateở mức page.
Kết quả: thời gian TTFB giảm đáng kể, kích thước bundle client tối thiểu, và dữ liệu vẫn được cập nhật thường xuyên.
Kết luận
Việc lựa chọn đúng chiến lược Data Fetching trong Next.js 15 – kết hợp Server Components, ISR và các API mới – giúp tối ưu hiệu năng, giảm tải server và cải thiện SEO. Nếu bạn muốn đi sâu hơn vào các kỹ thuật này và thực hành qua dự án thực tế, Tham khảo khóa học "Lập trình Front-End với NextJS + TypeScript" tại đây.


.jpg)
.jpg)
.png)



