Routing trong Next.js (App Router)
📋 Agenda
Thời gian đọc ước tính: ~15 phút
Sau bài này, bạn sẽ:
- ✅ Hiểu được tại sao Next.js dùng file-system routing và lợi thế của nó
- ✅ Phân biệt được
page.tsx,layout.tsx, vàloading.tsxdùng khi nào - ✅ Tự tay tạo được nested routes và dynamic segments từ đầu
- ✅ Nắm được cơ bản về cơ chế chuyển trang bằng
<Link>
Yêu cầu đầu vào (Prerequisites):
- 🔹 Biết cơ bản React component (JSX, props)
- 🔹 Đã cài Next.js và chạy được
npm run devít nhất một lần
❓ WHY — Tại sao routing trong Next.js lại đặc biệt?
Bạn đã bao giờ làm React thuần (Vite, CRA) và phải vật lộn với react-router-dom chưa? Bạn phải tự khai báo từng route, tự quản lý nested routes, rồi lại lo thêm code splitting, lazy loading...
// ❌ React thuần: Bạn tự làm mọi thứ
<Routes>
<Route path="/" element={<Home />} />
<Route path="/blog" element={<Blog />} />
<Route path="/blog/:slug" element={<BlogPost />} />
</Routes>
Vấn đề thực tế: Theo khảo sát cộng đồng React, hơn 65% lỗi routing trong các dự án vừa và lớn đến từ việc khai báo sai thứ tự route hoặc quên code splitting. Bảo trì khó, onboard teammate mới càng khó hơn.
Next.js App Router sinh ra để giải quyết chính xác bài toán đó:
- Không cần khai báo route — cấu trúc thư mục = cấu trúc URL
- Layouts tự động share trạng thái, không re-render
- Prefetching sẵn có, không cần cấu hình thêm
💡 Career path: Hiểu routing trong Next.js là kỹ năng tier 1 khi đi phỏng vấn Senior Frontend. Đây là phần interviewer hay hỏi nhất vì nó liên quan đến cả performance lẫn architecture.
📖 WHAT — File-system Routing là gì?
Ẩn dụ đời thường
Hãy tưởng tượng hệ thống routing của Next.js như một tòa nhà văn phòng nhiều tầng:
- Mỗi tầng (folder) = một URL segment
- Cửa ra vào (file
page.tsx) = nội dung hiển thị cho người vào tầng đó - Hành lang chung (file
layout.tsx) = UI dùng chung (header, sidebar) cho cả tầng và các tầng con bên trong - Văn phòng riêng theo tên (
[id]folder) = Dynamic route — cùng một layout nhưng nội dung thay đổi tùy người
Dù bạn vào tầng 1, tầng 2 hay tầng 10 — hành lang chung vẫn ở đó, không bị dựng lại mỗi lần bạn di chuyển.
Kiến trúc tổng quan
Các file convention quan trọng
| File | Vai trò | Ghi chú |
|---|---|---|
page.tsx | Nội dung trang, làm route accessible | Bắt buộc để route hoạt động |
layout.tsx | UI chia sẻ, wrap {children} | Không re-render khi navigate |
loading.tsx | UI fallback khi route đang load | Tự động wrap vào <Suspense> |
error.tsx | UI khi có lỗi xảy ra | Phải là 'use client' |
not-found.tsx | UI trang 404 | Trigger bởi notFound() |
🔨 HOW — Thực hành từng bước
Bước 1: Tạo Page đơn giản
Muốn có route /, tạo file app/page.tsx:
// filename: app/page.tsx
// Đây là Server Component — chạy trên server, không gửi JS xuống client
// → Phù hợp để fetch data, đọc DB trực tiếp
export default function HomePage() {
return <h1>Chào mừng đến trang chủ!</h1>
}
Muốn thêm route /about, thêm file app/about/page.tsx:
// filename: app/about/page.tsx
export default function AboutPage() {
return <h1>Giới thiệu về chúng tôi</h1>
}
✅ Không cần khai báo gì thêm — Next.js tự detect và đăng ký route.
Bước 2: Tạo Root Layout (Bắt buộc)
// filename: app/layout.tsx
// Root Layout là bắt buộc và phải chứa <html> + <body>
// Nó wraps TẤT CẢ các page trong ứng dụng
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="vi">
<body>
{/* Navbar ở đây sẽ xuất hiện trên MỌI page — không re-render khi navigate */}
<nav>My App</nav>
<main>{children}</main>
</body>
</html>
)
}