Để trở thành chuyên gia App Router, bạn phải nắm vững cách Next.js lưu trữ dữ liệu và cách bảo mật code của mình.
1. Bảo mật với server-only
Trong App Router, một file Server Component có thể vô tình bị import vào một Client Component. Nếu file đó chứa logic nhạy cảm (API Key, Database Secret), nó sẽ bị gửi về trình duyệt -> Lỗ hổng bảo mật.
Giải pháp: Sử dụng package server-only.
npm install server-only// lib/db-secret.ts
import 'server-only'; // 👈 Nếu ai đó import file này vào "use client", Next.js sẽ báo lỗi ngay khi build
export const API_KEY = process.env.SECRET_KEY;
export const db = ...;2. Hệ thống Caching 4 tầng
Next.js App Router rất "mạnh tay" trong việc cache. Bạn phải hiểu để tránh lỗi "Data không cập nhật".
Tầng 1: Request Memoization
React tự động cache các request fetch GIỐNG HỆT NHAU trong cùng một chu kỳ render (một lần tải trang).
- Lợi ích: Bạn có thể gọi
fetchUser()ở 5 component khác nhau, nhưng thực tế chỉ có 1 request được gửi đi.
Tầng 2: Data Cache
Next.js lưu trữ kết quả fetch qua nhiều request của nhiều người dùng khác nhau trên hệ thống.
- Duy trì: Vĩnh viễn (mặc định) cho đến khi
revalidate. - Cấu hình:
{ next: { revalidate: 3600 } }.
Tầng 3: Full Route Cache
Next.js render sẵn toàn bộ trang HTML và RSC Payload tại thời điểm build (Static Rendering).
- Mục tiêu: Tải trang ngay lập tức.
Tầng 4: Router Cache
Đây là cache phía Client (Trình duyệt). Next.js lưu trữ các trang bạn đã đi qua để khi bấm "Back", trang hiện ra tức thì mà không cần load lại.
3. Data Flow Pattern: Preloading
Nếu bạn có một cây component sâu và cần data, thay vì Waterfall (đợi cha xong rồi đến con), hãy dùng pattern Preload.
// components/User.tsx
import { getUser } from '@/lib/api';
export const preload = (id: string) => {
// Bắt đầu fetch sớm nhất có thể nhưng không đợi (non-blocking)
void getUser(id);
};
export default async function User({ id }: { id: string }) {
const user = await getUser(id); // Lúc này data có thể đã có sẵn trong cache memoization
return <div>{user.name}</div>;
}4. Server-Only Context (Singleton Pattern)
Trong Server Components, không có React Context. Nếu bạn muốn share dữ liệu xuyên suốt một request (ví dụ: currentUser), hãy dùng module singleton hoặc thư viện cache của React.
// lib/get-user.ts
import { cache } from 'react';
export const getCurrentUser = cache(async () => {
// Logic fetch user dựa trên cookie
return await db.user.findFirst(...);
});Nhờ hàm cache, dù bạn gọi getCurrentUser() bao nhiêu lần trong 1 request, logic chỉ chạy 1 lần.
Kết luận
- Luôn dùng
server-onlycho các file chứa secrets. - Hiểu rõ Data Cache để biết khi nào cần dùng
force-dynamichoặcrevalidatePath. - Tận dụng
cachecủa React để thay thế cho Context API trên Server.