
Lina Chen
Đăng ngày 12 tháng 11, 2025

Tìm hiểu sâu về App Router: layouts, route groups, parallel routes, loading states và các mẫu nâng cao cho ứng dụng có khả năng mở rộng.
Từ Next.js 13, App Router (thư mục app/) đã thay thế hệ thống pages/ cũ.
Đây không chỉ là thay đổi thư mục — đó là sự thay đổi mô hình hoàn toàn trong routing, layouts và data fetching.
Hãy cùng thành thạo nó. Từng bước một.
| Tính năng | Pages Router | App Router |
|---|---|---|
| Thư mục | pages/ | app/ |
| Layouts | _app.tsx + _document.tsx | layout.tsx (lồng nhau!) |
| Loading UI | Thủ công | loading.tsx (tự động!) |
| Route Groups | Không hỗ trợ | Thư mục (group) |
Mỗi thư mục có thể có layout.tsx → tự động lồng nhau.
app/├── layout.tsx // Root layout (html, body)├── dashboard/│ ├── layout.tsx // Dashboard shell (sidebar)│ └── page.tsx // Dashboard home└── blog/ └── layout.tsx // Blog layout (author bio)Không truyền props. Không code trùng lặp. Layouts wrap children tự động.
// app/dashboard/loading.tsxexport default function Loading() { return <div className="animate-pulse">Đang tải dashboard...</div>;}→ Hiển thị trong khi page.tsx đang fetch dữ liệu
// app/dashboard/error.tsx
'use client';
export default function Error({ error }: { error: Error }) {
return <p className="text-red-600">Lỗi: {error.message}</p>;
}
Sử dụng thư mục (group) để nhóm routes logic — không thay đổi URL.
app/├── (marketing)/│ ├── about/page.tsx → /about│ └── contact/page.tsx → /contact└── (app)/ └── dashboard/page.tsx → /dashboardHoàn hảo cho shared layouts, A/B testing, hoặc thư mục theo nhóm
Render nhiều page.tsx trong cùng layout sử dụng cú pháp @folder.
// app/dashboard/@analytics/page.tsxexport default function Analytics() { return <Chart />; }// app/dashboard/@team/page.tsxexport default function Team() { return <TeamList />; }// app/dashboard/layout.tsxexport default function Layout({ children, analytics, team,}: { children: React.ReactNode; analytics: React.ReactNode; team: React.ReactNode;}) {return ( <> <Sidebar /> <main>{children}</main> <aside>{analytics}</aside> <footer>{team}</footer> </>);}→ /dashboard hiển thị main + analytics + team đồng thời
Chặn một route mà không điều hướng — hoàn hảo cho modals.
// app/@modal/(.)photo/[id]/page.tsx// → /photo/123 → mở như modal, URL giữ nguyên /feedClick ảnh → modal mở, URL cập nhật, nút back đóng nó
// 1. Trộn app/ và pages/app/page.tsx + pages/api/hello.ts → Không thể đoán trước// 2. Chỉ đặt page.tsx ở rootapp/nested/page.tsx → Phải có thư mục!// 3. Quên 'use client' trong client components// 1. Sử dụng loading.tsx mọi nơiapp/settings/loading.tsx → UX tức thì// 2. Dùng route groups cho shared layoutsapp/(admin)/users/page.tsxapp/(admin)/settings/page.tsx// 3. Luôn export default từ page/layoutpages/ → app/(group) cho shared layoutsloading.tsx cho các trang chậm_app.tsx bằng nested layout.tsx@folder cho parallel routes(.)interceptionApp Router không chỉ là một thư mục mới.
Đó là React Server Components, streaming, nested layouts và modals không có JS — tất cả trong một.
Ngừng chiến đấu với _app.tsx.
Ngừng wrap layouts thủ công.
Hãy đón nhận App Router.
Ứng dụng của bạn sẽ nhanh hơn, sạch hơn và dễ bảo trì hơn.
Viết bởi Lina Chen
#NextJS #AppRouter #React #ServerComponents #WebDev #Frontend