Giới thiệu
Next.js là một framework mạnh mẽ cho phép xây dựng các trang web React có khả năng render phía server (SSR) và tĩnh (SSG). Khi triển khai một ứng dụng thực tế, việc tối ưu SSR không chỉ cải thiện tốc độ tải trang mà còn nâng cao SEO. Bài viết này sẽ hướng dẫn chi tiết cách tối ưu SSR trong Next.js 15 khi sử dụng TypeScript.
1. Khi nào nên dùng SSR?
SSR thích hợp cho các trang cần dữ liệu luôn cập nhật, ví dụ như dashboard người dùng, trang chi tiết sản phẩm với giá thay đổi liên tục, hoặc nội dung phụ thuộc vào quyền truy cập. Nếu dữ liệu ít thay đổi, bạn có thể cân nhắc Static Site Generation (SSG) để giảm tải server.
2. Cấu hình getServerSideProps trong TypeScript
Hàm getServerSideProps được chạy trên server mỗi khi người dùng yêu cầu trang. Để khai báo kiểu trả về, bạn nên sử dụng GetServerSideProps từ next và định nghĩa interface cho props.
import { GetServerSideProps, NextPage } from 'next';
import { fetchUserData } from '@/lib/api';
interface UserProps {
user: {
id: string;
name: string;
email: string;
};
}
const UserPage: NextPage = ({ user }) => (
<div>
<h1>Welcome, {user.name}</h1>
<p>Email: {user.email}</p>
</div>
);
export const getServerSideProps: GetServerSideProps = async (context) => {
const { id } = context.params as { id: string };
const user = await fetchUserData(id);
if (!user) {
return { notFound: true };
}
return { props: { user } };
};
export default UserPage;
Điều quan trọng là tránh thực hiện các tác vụ nặng trong getServerSideProps. Hãy tách các logic tính toán phức tạp ra các hàm riêng và chỉ thực hiện các truy vấn cần thiết.
3. Sử dụng Cache HTTP để giảm tải
Next.js cho phép thiết lập header cache trong getServerSideProps hoặc trong middleware. Ví dụ dưới đây thiết lập Cache-Control để cache kết quả trong 60 giây.
export const getServerSideProps: GetServerSideProps = async (context) => {
const data = await fetchData();
context.res.setHeader('Cache-Control', 'public, s-maxage=60, stale-while-revalidate=30');
return { props: { data } };
};
4. Middleware để xử lý xác thực và cache chung
Middleware trong Next.js 15 chạy trước khi tới bất kỳ route nào, cho phép bạn thực hiện kiểm tra quyền truy cập hoặc thiết lập cache chung.
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
// Cache static assets for 1 day
const response = NextResponse.next();
response.headers.set('Cache-Control', 'public, max-age=86400');
return response;
}
export const config = {
matcher: ['/dashboard/:path*', '/profile/:path*'],
};
5. Incremental Static Regeneration (ISR) cho dữ liệu ít thay đổi
Nếu dữ liệu không cần cập nhật mỗi lần truy cập, bạn có thể chuyển sang ISR. Điều này cho phép Next.js tái tạo trang tĩnh trong nền sau một khoảng thời gian nhất định.
export const getStaticProps: GetStaticProps = async () => {
const data = await fetchStaticData();
return {
props: { data },
revalidate: 300, // Tái tạo mỗi 5 phút
};
};
6. Kết hợp SWR cho fetch phía client
Khi cần cập nhật dữ liệu sau khi trang đã render, sử dụng swr giúp thực hiện revalidation một cách nhẹ nhàng mà không làm mất trải nghiệm người dùng.
import useSWR from 'swr';
import axios from 'axios';
const fetcher = (url: string) => axios.get(url).then(res => res.data);
function UserProfile({ initialData }: { initialData: User }) {
const { data, error } = useSWR('/api/user', fetcher, { fallbackData: initialData });
if (error) return <div>Failed to load</div>;
if (!data) return <div>Loading...</div>;
return (
<div>
<h2>{data.name}</h2>
<p>{data.email}</p>
</div>
);
}
Kết luận
Việc tối ưu SSR trong Next.js 15 đòi hỏi cân nhắc giữa thời gian phản hồi, chi phí server và yêu cầu cập nhật dữ liệu. Áp dụng các kỹ thuật cache, middleware, ISR và SWR sẽ giúp bạn xây dựng ứng dụng nhanh, ổn định và thân thiện với SEO.
Để nắm vững toàn bộ quy trình và thực hành trên 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.







