0
0
Lập trình
NM

Khám Phá App Router trong Next.js: Từ Pages Router đến Tính Năng Mới

Đăng vào 7 tháng trước

• 5 phút đọc

Giới Thiệu

Next.js 13.4 đã giới thiệu App Router như một bước tiến lớn so với Pages Router truyền thống. Được xây dựng trên React Server Components (RSC), kiến trúc mới này không chỉ cải thiện hiệu suất mà còn cho phép các mẫu UI phức tạp hơn, đồng thời hoàn toàn làm mới trải nghiệm của nhà phát triển.

Trong bài viết này, chúng ta sẽ tìm hiểu về sự so sánh giữa Pages Router và App Router, các quy tắc file, Suspense và Streaming, Parallel Routes và Intercepting Routes, thành phần <Link>, và middleware—tất cả những điểm thực tiễn mà bạn cần biết.


1. So Sánh: Pages Router và App Router

Hãy bắt đầu bằng việc so sánh Pages Router kế thừa với App Router mới để có cái nhìn tổng quát.

Tính Năng Pages Router App Router
Thư mục pages/ app/
Loại Thành Phần Thành phần Client theo mặc định Thành phần Server theo mặc định (sử dụng use client để chuyển đổi)
Lấy Dữ Liệu getStaticProps / getServerSideProps Lời gọi fetch trực tiếp trên server
Layouts _app.tsx / _document.tsx layout.tsx (hỗ trợ layout lồng nhau)
Định Tuyến Phẳng, dựa trên file Dựa trên cấu trúc thư mục, hỗ trợ Nhóm Tuyến
Giao Diện Bị Trì Hoãn Triển khai thủ công Suspense + loading.tsx + Streaming
Xử Lý Lỗi _error.tsx / 404.tsx error.tsx / not-found.tsx
Đường Dẫn API pages/api/*.ts route.ts
UI Phức Tạp / Modal Triển khai với logic trạng thái và điều kiện Hỗ trợ chính thức với Parallel Routes / Intercepting Routes
SEO / Metadata next/head API metadata với tính an toàn về kiểu

👉 App Router tiến tới sự phân tách rõ ràng về trách nhiệm và hỗ trợ chính thức cho các mẫu UI phức tạp.


2. Quy Tắc File trong App Router

Trong App Router, việc đặt các file đặc biệt trong thư mục app/ sẽ xác định định tuyến và hành vi UI.

File Mục Đích
page.tsx Thành phần trang chính, ánh xạ đến URL.
layout.tsx Layout chia sẻ. Lồng nhau và duy trì trong các chuyển tiếp trang.
template.tsx Tương tự như layout.tsx nhưng sẽ tái mount khi điều hướng (ví dụ: đặt lại form).
loading.tsx UI tải trong quá trình lấy dữ liệu. Tự động làm việc với Suspense.
error.tsx Ranh giới lỗi cho tuyến đường.
not-found.tsx UI 404 tùy chỉnh cho tuyến đường.
route.ts Xác định các đường dẫn API bằng cách xuất các hàm cho các phương thức HTTP.
default.tsx UI mặc định cho Parallel Routes khi không có gì được chọn.
Thư mục (group) Nhóm cho mục đích tổ chức mà không ảnh hưởng đến URL.
Thư mục [param] Các tuyến đường động, ví dụ: /users/[id].

👉 Khả năng tách biệt xử lý tải, lỗi và không tìm thấy theo từng tuyến đường là một bước tiến lớn về độ rõ ràng và khả năng bảo trì.


3. Suspense và Streaming

Suspense

<Suspense> hiển thị một UI dự phòng trong khi dữ liệu đang được lấy hoặc các thành phần đang được tải lười biếng.

tsx Copy
<Suspense fallback={<p>Đang tải bình luận...</p>}>
  <Comments />
</Suspense>

👉 Trong khi đang lấy dữ liệu, nó sẽ hiển thị “Đang tải bình luận...”, sau đó chuyển đổi liền mạch sang UI cuối cùng khi đã sẵn sàng.

Streaming

Streaming gửi HTML tới client ngay khi mỗi phần đã sẵn sàng, thay vì chờ đợi toàn bộ trang. Điều này loại bỏ nỗi lo “chờ màn hình trắng”, dẫn đến trải nghiệm người dùng mượt mà hơn.


4. Parallel Routes và Intercepting Routes

Parallel Routes

Cho phép hiển thị nhiều tuyến đường đồng thời.

Ví dụ: Trong một ứng dụng email, hiển thị “hộp thư đến” và “chi tiết” bên cạnh nhau.

tsx Copy
// layout.tsx
export default function Layout({ inbox, detail }: { inbox: React.ReactNode, detail: React.ReactNode }) {
  return (
    <div className="grid grid-cols-2">
      <div>{inbox}</div>
      <div>{detail}</div>
    </div>
  );
}

Intercepting Routes

Chặn điều hướng và thay thế nó bằng một giao diện thay thế, chẳng hạn như một modal.

Ví dụ: Hiển thị trang chi tiết sản phẩm bên trong một modal khi nhấp vào.

👉 Điều này kết hợp điều hướng modal theo kiểu SPA với việc hiển thị toàn trang khi được truy cập trực tiếp.


Thành phần <Link> cho phép điều hướng client-side nhanh chóng trong Next.js.

Cách Hoạt Động

  1. Khi một <Link> vào viewport, Next.js prefetches tài nguyên cho trang đích.
  2. Khi nhấp vào, các tài nguyên đã được tải trước sẽ được sử dụng ngay lập tức.
  3. Việc điều hướng trang hoàn tất gần như ngay lập tức.

👉 Nhờ prefetching, việc điều hướng cảm giác như chuyển trang tức thì.


6. Middleware

Tổng Quan

middleware.ts chạy ngay sau khi một yêu cầu đến server, trước khi render một trang hoặc tuyến API.

Các Trường Hợp Sử Dụng Thông Thường

  • Kiểm tra xác thực: Chuyển hướng người dùng chưa xác thực đến /login.
  • Phát hiện ngôn ngữ: Chuyển hướng dựa trên tiêu đề Accept-Language.
  • Kiểm tra A/B: Chia lưu lượng giữa các biến thể.
  • Kiểm soát truy cập: Chặn yêu cầu dựa trên IP hoặc user-agent.

Ví Dụ

ts Copy
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  const token = request.cookies.get("token");

  if (!token && request.nextUrl.pathname.startsWith("/dashboard")) {
    return NextResponse.redirect(new URL("/login", request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/dashboard/:path*"],
};

👉 Điều này cho phép bạn thực thi kiểm tra xác thực và chuyển hướng trước khi bất kỳ logic trang nào chạy.


Kết Luận

  • Những tiến bộ của App Router
    • Layout lồng nhau, quy tắc file rõ ràng, và Streaming/Suspense cho trải nghiệm người dùng cải thiện.
    • UI phức tạp được hỗ trợ chính thức với Parallel Routes và Intercepting Routes.
  • Lợi ích của <Link>
    • Prefetching cho phép điều hướng client-side cảm giác ngay lập tức.
  • Sức mạnh của Middleware
    • Thực hiện kiểm tra xác thực, chuyển hướng, và phát hiện ngôn ngữ ngay sau khi yêu cầu đến.

👉 Đối với các dự án mới, App Router được khuyến nghị mạnh mẽ. Đối với các dự án hiện tại, hãy di chuyển từng bước để tránh rủi ro.


Tài Nguyên Tham Khảo

  • Cơ bản về App Router và cấu trúc file (Zenn)
  • Bài viết về App Router trong Next.js (Zenn)
Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào