Next.js là gì? Vấn đề nó giải quyết
React tự thân chỉ là thư viện UI — nó không có routing, không có cơ chế render phía server, không có data fetching layer chuẩn. Next.js bổ sung:- File-based routing qua thư mục
app/ - React Server Components (RSC) — component render trên server, không gửi JS xuống client
- Streaming SSR — gửi HTML dần theo từng phần sẵn sàng, kết hợp
<Suspense> - Cache Components — cache khai báo ở mức function/component, thay cho cơ chế cache ẩn của Next.js 13-15
- Route Handlers, Server Actions — viết backend logic ngay trong cùng codebase
- Turbopack (ổn định từ v16) — bundler thay thế Webpack, build nhanh hơn 5-10 lần
So với tự dựng React app thuần
Các khái niệm cốt lõi
App Router — quy ước file trong thư mục app/
Mỗi thư mục trong app/ là một segment URL. File đặc biệt trong thư mục quyết định hành vi:
[id]— dynamic segment, đọc bằngparamstrong component[...slug]— catch-all segment(group)— route group, dùng để tổ chức code mà không ảnh hưởng URL@slot— parallel route, dùng cho UI hiện song song (modal, tab)
params và searchParams là Promise — phải await trước khi dùng. Đây là thay đổi hay bị bỏ sót khi migrate từ bản cũ.generateStaticParams — sinh sẵn danh sách params lúc build:
cacheComponents: true, các params không nằm trong danh sách trả về từ generateStaticParams vẫn render được — chỉ khác là render động tại request thay vì phục vụ từ bản build sẵn.
export const runtime — chọn runtime cho từng route:
edge cho các route chỉ đọc/ghi qua fetch (không dùng driver DB cần Node.js) để giảm cold start. proxy.ts (mục bên dưới) từ Next.js 16 mặc định chạy Node.js runtime, không còn Edge Runtime như middleware.ts trước đây.
Components — Server Component là mặc định
Mọi component trongapp/ là Server Component trừ khi có 'use client' ở đầu file.
Server vs Client Components
Đây là ranh giới quan trọng nhất khi thiết kế component tree trong App Router.Server Component
- Không có
'use client' async/awaittrực tiếp trong component, gọi DB/API an toàn- Không dùng được
useState,useEffect, event handler - Không gửi JS xuống bundle client
Client Component
- Bắt đầu bằng
'use client' - Dùng được hook (
useState,useEffect), event handler, browser API - Vẫn được prerender HTML lần đầu (không phải CSR thuần)
- Tăng kích thước JS bundle gửi về client
Layout — khung dùng chung, không remount khi điều hướng
layout.tsx giữ nguyên state và không re-render khi chuyển route con — chỉ children (nội dung page.tsx) thay đổi. Đây là lý do sidebar/header không bị “nháy” khi chuyển trang.
loading.tsx và error.tsx — trạng thái tải và lỗi theo từng route
Next.js tự bọcpage.tsx trong một <Suspense> ngầm định nếu có loading.tsx cùng cấp, và trong một error boundary nếu có error.tsx.
reset() chạy lại render của segment bị lỗi mà không cần reload cả trang. Nếu lỗi xảy ra ở layout.tsx gốc (không có error.tsx nào bắt được), Next.js rơi xuống app/global-error.tsx — file này phải tự bọc cả thẻ <html>/<body> vì nó thay thế luôn root layout.
Metadata, Image, Font — tối ưu tích hợp sẵn
Metadata API thay thế việc tự viết thẻ<head> — dùng export const metadata (tĩnh) hoặc generateMetadata (động, cần data):
next/image tự động resize, chuyển định dạng (WebP/AVIF), và lazy-load ảnh:
next/font tự host font (Google Fonts hoặc font cục bộ), loại bỏ layout shift khi font load xong:
Route Handlers — backend API trong app/api/
Route Handlers thay thế API Routes của Pages Router (pages/api/*.ts). Đặt trong route.ts, export theo tên HTTP method.
Server Actions — mutation gắn trực tiếp vào component
Server Action là một async function chạy trên server, gọi được thẳng từ Client Component hoặc gắn vào<form action={...}> — không cần định nghĩa route riêng như Route Handler.
useActionState (React 19, tích hợp sẵn trong Next.js 16) quản lý pending state và kết quả trả về từ Server Action mà không cần tự viết useState/useEffect cho việc gọi API.
<form>) — khác với gọi Route Handler bằng fetch từ Client Component, vốn phụ thuộc hoàn toàn vào JS đã chạy.Cache Components — mô hình cache của Next.js 16
Đây là thay đổi kiến trúc lớn nhất của bản 16: cache chuyển từ ngầm định (mặc định cache mọi thứ, phải opt-out) sang tường minh (mặc định không cache gì, opt-in bằng'use cache').
Bật trong next.config.ts:
Mặc định: dynamic — không cache
Mặc định: dynamic — không cache
'use cache' → route render động ở mọi request, fetch() không tự cache (khác hẳn Next.js 13-15, nơi fetch được cache ngầm định).'use cache' — cache tường minh
'use cache' — cache tường minh
cacheLife — kiểm soát thời gian sống
cacheLife — kiểm soát thời gian sống
stale / revalidate / expire (giây).cacheTag + revalidateTag — invalidate theo tag
cacheTag + revalidateTag — invalidate theo tag
revalidatePath để xóa cache theo cả một route:revalidateTag ưu tiên hơn khi có thể, vì chỉ xóa đúng entry liên quan thay vì cả route.Partial Prerendering (PPR) — trộn tĩnh và động trong 1 route
Partial Prerendering (PPR) — trộn tĩnh và động trong 1 route
<Suspense>; phần còn lại của route được prerender tĩnh và phục vụ ngay lập tức, phần trong Suspense stream sau.cacheComponents:
Middleware → proxy.ts
Next.js 16 đổi tên middleware.ts thành proxy.ts (export proxy thay vì middleware) để làm rõ đây là lớp chặn request trước khi route render — không phải nơi đặt business logic.
middleware.ts vẫn chạy được (deprecated, có warning). Runtime cũng đổi: proxy.ts chạy trên Node.js runtime thay vì Edge Runtime mặc định trước đây — ảnh hưởng đến cách xử lý cookie/session trong logic auth. Có codemod hỗ trợ: npx @next/codemod@canary middleware-to-proxy.Next.js + Claude Code trong workflow lập trình
Khi làm việc với Claude Code trên một dự án Next.js, mô tả càng cụ thể theo đúng API/convention của framework, kết quả càng chính xác — tránh mô tả chung chung để Claude tự đoán giữa Route Handler, Server Action, hay client fetch. Ví dụ yêu cầu rõ ràng, đúng ngữ cảnh kỹ thuật:Kiến trúc tổng thể
So sánh với các lựa chọn khác
Bắt đầu
Khởi tạo dự án
create-next-app với flag --app (App Router) và --turbopack.Bật cacheComponents và thiết lập cache profile
cacheComponents: true, sau đó áp 'use cache' dần cho các route/hàm ít thay đổi trước (landing page, blog).Tách Server/Client Component theo boundary nhỏ nhất
'use client' ở component thực sự cần tương tác/browser API, không đẩy lên cả layout.Câu hỏi thường gặp
Route Handler và Server Action khác nhau khi nào nên dùng cái nào?
Route Handler và Server Action khác nhau khi nào nên dùng cái nào?
route.ts) là HTTP endpoint thật sự — dùng khi cần một URL cụ thể (webhook, API cho mobile client, tích hợp bên thứ 3 gọi vào).Server Action ('use server') là hàm gọi trực tiếp từ component, không cần định nghĩa route — phù hợp cho mutation gắn liền với 1 form/UI cụ thể, tận dụng progressive enhancement của <form action={...}>.cacheComponents có phải bật ngay không? Có breaking change gì?
cacheComponents có phải bật ngay không? Có breaking change gì?
fetch() không còn tự cache mặc định, revalidate export bị loại bỏ (dùng cacheLife trong scope 'use cache' thay thế), dynamic = 'force-static' được thay bằng 'use cache' + cacheLife('max'). Với dự án cũ đang dùng Next.js 13-15, cần audit lại toàn bộ chỗ đang phụ thuộc vào cache ngầm định trước khi bật.proxy.ts chạy ở runtime nào?
proxy.ts chạy ở runtime nào?
middleware.ts dùng trước đây). Ảnh hưởng trực tiếp đến logic xử lý cookie/session trong auth — cần kiểm tra lại các thư viện auth (NextAuth/Auth.js, Clerk, v.v.) có tương thích runtime mới không khi migrate.Turbopack thay Webpack hoàn toàn chưa?
Turbopack thay Webpack hoàn toàn chưa?
next dev và next build (đã ổn định, không còn gắn cờ --turbo). Webpack vẫn dùng được qua cấu hình, nhưng chỉ nên giữ lại nếu có plugin Webpack chưa có tương đương cho Turbopack.Next.js có phù hợp cho monorepo không?
Next.js có phù hợp cho monorepo không?
Tóm tắt
App Router
app/: page.tsx, layout.tsx, route.ts, dynamic segments [id], route groups (name).Server & Client Components
'use client' chỉ ở boundary tương tác nhỏ nhất.Cache Components
'use cache', cacheLife, cacheTag/revalidateTag. Partial Prerendering trộn tĩnh và động trong cùng route.Route Handlers & proxy.ts
app/api/**/route.ts. proxy.ts (Node.js runtime) chặn request trước khi route render.Next.js 16 chuyển cache từ ngầm định sang tường minh (Cache Components), ổn định Turbopack, và đổimiddleware.tsthànhproxy.ts. Đây là bản nâng cấp về tính đúng đắn và hiệu năng hơn là tính năng bề mặt — audit kỹ phần cache khi migrate từ 13-15.