Series 5 – Next.js Fundamentals

 

Bài 3:Route Groups, Catch-all Routes và Navigation trong Next.js

 

1. Mở đầu

Khi xây dựng một ứng dụng web, việc tạo các trang riêng lẻ chỉ là bước đầu. Khi ứng dụng phát triển, chúng ta cần tổ chức các trang theo từng nhóm chức năng, xử lý những đường dẫn có cấu trúc phức tạp và giúp người dùng di chuyển giữa các trang một cách thuận tiện.

Trong Next.js App Router, ngoài Static Routes, Dynamic Routes và Nested Routes, chúng ta còn có những cơ chế như Route Groups, Catch-all Routes và các công cụ Navigation.

Bài viết này sẽ giúp bạn hiểu cách sử dụng những cơ chế đó và biết khi nào nên áp dụng chúng vào dự án thực tế.

2. Route Groups là gì?

Route Groups cho phép nhóm các route theo chức năng hoặc mục đích tổ chức mã nguồn mà không làm thay đổi URL của trang.

Để tạo Route Group, chúng ta đặt tên thư mục bên trong dấu ngoặc đơn.

Ví dụ, một website có trang giới thiệu, trang đăng nhập và trang quản trị có thể được tổ chức như sau:

src/
└── app/
    ├── (marketing)/
    │   ├── page.tsx
    │   └── about/
    │       └── page.tsx
    ├── (auth)/
    │   └── login/
    │       └── page.tsx
    └── (dashboard)/
        └── dashboard/
            └── page.tsx

Mặc dù các thư mục được chia thành nhiều nhóm, URL vẫn được xác định bởi những thư mục route thông thường bên trong chúng.

File URL
(marketing)/page.tsx /
(marketing)/about/page.tsx /about
(auth)/login/page.tsx /login
(dashboard)/dashboard/page.tsx /dashboard

Tên (marketing), (auth) và (dashboard) không xuất hiện trong URL.

Khi nào nên sử dụng Route Groups?

Route Groups hữu ích khi bạn muốn:

  • Phân chia mã nguồn theo từng khu vực chức năng.
  • Tổ chức các trang có mục đích khác nhau.
  • Áp dụng layout riêng cho từng nhóm trang.
  • Giúp cấu trúc dự án dễ đọc và bảo trì hơn khi số lượng trang tăng lên.

Một lưu ý quan trọng là các Route Groups không được tạo ra những route trùng URL. Ví dụ, (marketing)/about/page.tsx và (dashboard)/about/page.tsx đều ánh xạ đến /about, vì vậy sẽ gây xung đột.

3. Catch-all Routes là gì?

Trong một số ứng dụng, chúng ta không thể biết trước số lượng segment xuất hiện trong URL.

Ví dụ, một website thương mại điện tử có thể có các đường dẫn:

/shop/clothing
/shop/clothing/shirts
/shop/clothing/shirts/t-shirts

Thay vì tạo riêng từng thư mục cho mọi trường hợp, Next.js cho phép sử dụng Catch-all Routes để bắt nhiều segment phía sau một đường dẫn.

3.1. Catch-all Route

Cú pháp sử dụng ba dấu chấm bên trong cặp ngoặc vuông:

src/app/shop/[...slug]/page.tsx

Route này có thể khớp với:

/shop/clothing
/shop/clothing/shirts
/shop/clothing/shirts/t-shirts

Trong page.tsx, tham số slug chứa một mảng các segment của URL.

Ví dụ với phiên bản Next.js sử dụng Promise cho params:

type PageProps = {
  params: Promise<{
    slug: string[];
  }>;
};

export default async function ShopPage({
  params,
}: PageProps) {
  const { slug } = await params;

  return (
    <main>
      <h1>Shop</h1>
      <p>{slug.join(" / ")}</p>
    </main>
  );
}

Nếu người dùng truy cập /shop/clothing/shirts, giá trị của slug sẽ là:

["clothing", "shirts"]

Kết quả hiển thị:

Shop
clothing / shirts

Cần lưu ý rằng params ở đây là Promise theo cách viết hiện hành của Next.js App Router. Một số phiên bản Next.js cũ sử dụng kiểu params đồng bộ.

3.2. Optional Catch-all Route

Nếu muốn route cũng khớp khi không có segment phía sau /shop, chúng ta sử dụng hai dấu ngoặc vuông:

src/app/shop/[[...slug]]/page.tsx

Route này có thể xử lý cả:

/shop
/shop/clothing
/shop/clothing/shirts

Khi truy cập /shop, slug có giá trị undefined. Khi truy cập /shop/clothing, slug là ["clothing"].

3.3. Phân biệt hai loại Catch-all

Loại route Cú pháp Có khớp URL gốc không?
Catch-all [...slug] Không
Optional Catch-all [[...slug]] Có

Catch-all Routes phù hợp với hệ thống danh mục nhiều cấp, trang tài liệu có cấu trúc phân cấp hoặc các đường dẫn được tạo từ dữ liệu động.

Tuy nhiên, không nên sử dụng chúng cho mọi route. Nếu cấu trúc URL đã rõ ràng, các thư mục route thông thường sẽ dễ đọc và dễ bảo trì hơn.

4. Navigation trong Next.js

Navigation là quá trình chuyển từ trang này sang trang khác.

Trong Next.js App Router, chúng ta thường sử dụng ba cách chính:

  • Link để tạo liên kết giữa các trang.
  • useRouter để điều hướng bằng JavaScript trong Client Components.
  • redirect để chuyển hướng trong những tình huống phù hợp ở phía server.

4.1. Sử dụng Link

Thay vì dùng thẻ <a> cho mọi liên kết nội bộ, Next.js cung cấp component Link.

import Link from "next/link";

export default function Header() {
  return (
    <nav>
      <Link href="/">Trang chủ</Link>
      <Link href="/about">Giới thiệu</Link>
      <Link href="/shop">Cửa hàng</Link>
    </nav>
  );
}

Link hỗ trợ điều hướng nội bộ và có thể tự động prefetch route khi liên kết xuất hiện trong vùng nhìn thấy của trình duyệt, tùy loại route và cấu hình.

Điều này giúp việc chuyển trang trong ứng dụng Next.js thường mượt mà hơn so với tải lại toàn bộ trang.

Với liên kết đến một website bên ngoài, thẻ <a> vẫn là lựa chọn phù hợp:

<a
  href="https://nextjs.org"
  target="_blank"
  rel="noreferrer"
>
  Tài liệu Next.js
</a>

4.2. Sử dụng useRouter

Đôi khi chúng ta muốn điều hướng sau một hành động, chẳng hạn sau khi người dùng hoàn thành biểu mẫu.

Trong trường hợp đó, useRouter có thể được sử dụng trong Client Component.

"use client";

import { useRouter } from "next/navigation";

export default function LoginButton() {
  const router = useRouter();

  function handleLogin() {
    // Ví dụ minh họa:
    // Chỉ điều hướng sau khi đăng nhập thành công.
    router.push("/dashboard");
  }

  return (
    <button onClick={handleLogin}>
      Đăng nhập
    </button>
  );
}

Một số phương thức thường gặp:

Phương thức Công dụng
router.push() Chuyển đến URL mới và thêm lịch sử điều hướng
router.replace() Chuyển đến URL mới nhưng thay thế mục lịch sử hiện tại
router.back() Quay lại trang trước
router.refresh() Yêu cầu làm mới dữ liệu hiển thị từ phía server mà không tải lại toàn bộ tài liệu

Lưu ý: Không nên chuyển đến /dashboard chỉ vì người dùng đã bấm nút. Trong ứng dụng thật, cần kiểm tra kết quả xác thực trước khi điều hướng, đồng thời bảo vệ dữ liệu và route ở phía server.

4.3. Sử dụng redirect

redirect hữu ích khi cần chuyển hướng theo logic phía server, chẳng hạn khi một trang không nên tiếp tục hiển thị với người dùng chưa đăng nhập.

import { redirect } from "next/navigation";

export default async function DashboardPage() {
  const isAuthenticated = false; // Ví dụ minh họa

  if (!isAuthenticated) {
    redirect("/login");
  }

  return <h1>Dashboard</h1>;
}

Đoạn code trên chỉ minh họa vị trí sử dụng redirect. Trong ứng dụng thật, isAuthenticated phải được xác định bằng cơ chế xác thực đáng tin cậy phía server.

5. Những điều cần lưu ý

Khi làm việc với routing trong Next.js, bạn nên nhớ:

  1. Route Groups dùng để tổ chức mã nguồn, không xuất hiện trong URL.
  2. Catch-all Routes dành cho những đường dẫn có số lượng segment thay đổi.
  3. Dùng Link cho phần lớn liên kết nội bộ.
  4. Dùng useRouter khi cần điều hướng bằng logic phía client.
  5. Dùng redirect cho những tình huống chuyển hướng phù hợp ở phía server.
  6. Không xem việc ẩn nút hoặc chuyển hướng ở frontend là biện pháp bảo mật đầy đủ.

6. Bài tập thực hành

Hãy xây dựng cấu trúc routing cho một website bán hàng với các yêu cầu:

  • Có trang chủ /.
  • Có trang giới thiệu /about.
  • Có trang đăng nhập /login.
  • Có trang quản trị /dashboard.
  • Có trang danh mục sản phẩm hỗ trợ nhiều cấp, ví dụ /shop/clothing/shirts.
  • Có thanh điều hướng để chuyển giữa trang chủ, giới thiệu và cửa hàng.

Hãy thử tổ chức trang bằng Route Groups, tạo Catch-all Route cho danh mục và sử dụng Link để điều hướng.

7. Kết luận

Route Groups giúp mã nguồn được tổ chức theo từng khu vực chức năng. Catch-all Routes hỗ trợ các đường dẫn có cấu trúc linh hoạt, còn Navigation cung cấp những cách điều hướng phù hợp với từng tình huống trong ứng dụng.

Khi đã nắm được cách tổ chức và chuyển đổi giữa các route, bước tiếp theo là tìm hiểu cách chia sẻ giao diện chung, hiển thị trạng thái tải dữ liệu và xử lý lỗi.

Đây là nội dung của bài tiếp theo: Layouts, Loading UI, Error Handling và Proxy trong Next.js.

Tài liệu tham khảo

 

 

 

 

Bài 4:Layouts, Loading UI, Error Handling và Proxy trong Next.js

 

 

1. Mở đầu

Khi xây dựng một ứng dụng Next.js, việc tạo route và điều hướng giữa các trang mới chỉ giải quyết một phần của bài toán.

Một ứng dụng hoàn chỉnh còn cần những thành phần dùng chung như header, footer và sidebar. Ngoài ra, người dùng cũng cần được thông báo khi dữ liệu đang tải, khi trang không tồn tại hoặc khi xảy ra lỗi trong quá trình hiển thị.

Next.js App Router cung cấp các quy ước file giúp xử lý những trường hợp này một cách có tổ chức, bao gồm layout.tsx, loading.tsx, error.tsx, not-found.tsx và proxy.ts.

2. Layouts: Tái sử dụng giao diện giữa các trang

Layout là thành phần dùng để chia sẻ giao diện chung giữa nhiều trang.

Ví dụ, một website có thể có header, thanh điều hướng và footer xuất hiện trên hầu hết các trang. Thay vì viết lại những thành phần này trong từng page.tsx, chúng ta có thể đặt chúng vào layout.

2.1. Root Layout

Trong App Router, app/layout.tsx là Root Layout. Đây là layout gốc của ứng dụng và phải chứa các thẻ <html> cùng <body>.

Ví dụ:

import type { ReactNode } from "react";

export default function RootLayout({
  children,
}: {
  children: ReactNode;
}) {
  return (
    <html lang="vi">
      <body>
        {children}
      </body>
    </html>
  );
}

Ở đây, children đại diện cho nội dung của trang hoặc layout con được hiển thị bên trong layout hiện tại.

Khi người dùng truy cập một route, Next.js sẽ kết hợp layout phù hợp với nội dung của trang đó.

2.2. Nested Layouts

Ngoài Root Layout, chúng ta có thể tạo layout bên trong từng khu vực.

Ví dụ:

src/
└── app/
    ├── layout.tsx
    ├── page.tsx
    ├── blog/
    │   ├── layout.tsx
    │   ├── page.tsx
    │   └── [slug]/
    │       └── page.tsx
    └── dashboard/
        ├── layout.tsx
        └── page.tsx

Trong cấu trúc này:

  • app/layout.tsx là Root Layout.
  • app/blog/layout.tsx áp dụng cho các trang trong khu vực blog.
  • app/dashboard/layout.tsx áp dụng cho các trang trong khu vực dashboard.

Ví dụ, layout của blog có thể chứa thanh điều hướng riêng:

import type { ReactNode } from "react";

export default function BlogLayout({
  children,
}: {
  children: ReactNode;
}) {
  return (
    <section>
      <nav>
        <a href="/blog">Tất cả bài viết</a>
      </nav>

      <main>{children}</main>
    </section>
  );
}

Trong dự án thực tế, bạn có thể sử dụng Link thay cho thẻ <a> khi điều hướng giữa các route nội bộ.

2.3. Layout có bị tạo lại khi chuyển trang không?

Một đặc điểm quan trọng của App Router là layout dùng chung có thể được giữ lại khi người dùng điều hướng giữa các route con.

Điều này giúp tránh việc phải tạo lại toàn bộ giao diện chung sau mỗi lần chuyển trang.

Tuy nhiên, không nên xem layout là nơi phù hợp để đặt mọi trạng thái. Nếu một trạng thái cần thay đổi theo route, hãy cân nhắc cách quản lý trạng thái đó và xác định thành phần nào thực sự cần sở hữu nó.

3. Loading UI: Hiển thị trạng thái đang tải

Trong ứng dụng thực tế, có những trang cần thời gian để lấy dữ liệu từ API hoặc xử lý nội dung phía server.

Nếu không có phản hồi trực quan, người dùng có thể nghĩ rằng trang đang bị treo.

Next.js cho phép tạo file loading.tsx để hiển thị giao diện tải dữ liệu cho một route segment.

Ví dụ:

src/app/blog/
├── page.tsx
├── loading.tsx
└── [slug]/
    └── page.tsx

Nội dung của loading.tsx:

export default function Loading() {
  return (
    <div>
      <p>Đang tải bài viết...</p>
    </div>
  );
}

Next.js sử dụng loading.tsx để cung cấp giao diện dự phòng trong lúc nội dung tương ứng đang được tải hoặc render. Cơ chế này được tích hợp với Suspense và streaming.

Khi nào nên sử dụng Loading UI?

Bạn nên cân nhắc tạo Loading UI khi:

  • Trang cần tải dữ liệu từ API.
  • Nội dung cần thời gian xử lý phía server.
  • Người dùng cần phản hồi ngay sau khi chuyển trang.
  • Bạn muốn dùng skeleton thay vì một dòng thông báo đơn giản.

Ví dụ, một trang danh sách sản phẩm có thể hiển thị các khung sản phẩm giả lập trước khi dữ liệu thực sự xuất hiện.

Lưu ý rằng loading.tsx không thay thế việc xử lý lỗi. Nếu quá trình tải thất bại, bạn cần một cơ chế xử lý lỗi phù hợp.

4. Error Handling: Xử lý lỗi trong ứng dụng

Trong quá trình hoạt động, ứng dụng có thể gặp lỗi khi render component, lấy dữ liệu hoặc thực hiện những thao tác khác.

Nếu không xử lý, một lỗi không được bắt có thể khiến khu vực giao diện liên quan không hiển thị đúng.

Next.js hỗ trợ Error Boundary thông qua file error.tsx.

4.1. Tạo error.tsx

Ví dụ cấu trúc:

src/app/blog/
├── page.tsx
├── error.tsx
└── [slug]/
    └── page.tsx

Nội dung error.tsx:

"use client";

import { useEffect } from "react";

export default function BlogError({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    console.error(error);
  }, [error]);

  return (
    <section>
      <h2>Đã xảy ra lỗi!</h2>
      <p>Không thể hiển thị nội dung. Vui lòng thử lại.</p>

      <button onClick={() => reset()}>
        Thử lại
      </button>
    </section>
  );
}

Trong ví dụ trên:

  • error chứa thông tin về lỗi.
  • reset() yêu cầu Next.js thử render lại khu vực được Error Boundary quản lý.
  • "use client" cần thiết vì component sử dụng hook và sự kiện của trình duyệt.

Trong ứng dụng thật, nên ghi nhận lỗi bằng hệ thống logging phù hợp và tránh hiển thị thông tin nhạy cảm từ lỗi nội bộ cho người dùng.

4.2. Error Boundary xử lý được những lỗi nào?

error.tsx chủ yếu xử lý các lỗi phát sinh trong quá trình render và những hoạt động thuộc phạm vi Error Boundary.

Nó không tự động xử lý mọi lỗi có thể xuất hiện trong ứng dụng. Ví dụ, lỗi xảy ra trong event handler hoặc một tác vụ bất đồng bộ chạy độc lập cần được xử lý phù hợp tại nơi thực hiện tác vụ đó.

Ngoài ra, error.tsx không bắt lỗi từ layout cùng cấp nằm phía trên nó. Nếu cần xử lý lỗi tại Root Layout, Next.js cung cấp cơ chế global-error.tsx.

5. not-found.tsx: Xử lý trang không tồn tại

Không phải mọi URL mà người dùng nhập đều tương ứng với một trang hợp lệ.

Ví dụ, người dùng có thể truy cập một bài blog không tồn tại hoặc một sản phẩm đã bị xóa.

Next.js cung cấp file not-found.tsx để xây dựng giao diện 404.

src/app/
├── layout.tsx
├── page.tsx
└── not-found.tsx

Ví dụ:

import Link from "next/link";

export default function NotFound() {
  return (
    <main>
      <h1>404 - Không tìm thấy trang</h1>
      <p>Trang bạn đang tìm kiếm không tồn tại.</p>

      <Link href="/">
        Quay về trang chủ
      </Link>
    </main>
  );
}

Khi cần xác định rằng một tài nguyên không tồn tại, bạn có thể sử dụng hàm notFound() từ next/navigation trong những tình huống phù hợp.

Ví dụ:

import { notFound } from "next/navigation";

export default async function ProductPage() {
  const product = null; // Ví dụ minh họa

  if (!product) {
    notFound();
  }

  return <h1>Chi tiết sản phẩm</h1>;
}

Đây chỉ là ví dụ minh họa; trong ứng dụng thật, product cần được lấy từ nguồn dữ liệu thực tế.

Cần phân biệt giữa lỗi không tìm thấy tài nguyên và lỗi hệ thống. Một sản phẩm không tồn tại thường phù hợp với giao diện 404, trong khi lỗi kết nối cơ sở dữ liệu có thể cần được xử lý như lỗi hệ thống.

6. Proxy trong Next.js

Proxy cho phép chạy logic trước khi request được xử lý hoàn tất. Nó có thể được dùng để chuyển hướng, rewrite URL, chỉnh sửa header hoặc phản hồi trực tiếp.

Từ Next.js 16, quy ước middleware.ts đã được đổi tên thành proxy.ts. Nếu dự án của bạn đang sử dụng phiên bản Next.js cũ hơn, hãy kiểm tra tài liệu tương ứng với phiên bản đó.

6.1. Ví dụ về Proxy

Trong dự án có thư mục src/app, file có thể được đặt tại src/proxy.ts:

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

export function proxy(request: NextRequest) {
  if (request.nextUrl.pathname === "/old-page") {
    return NextResponse.redirect(
      new URL("/new-page", request.url)
    );
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/old-page"],
};

Trong ví dụ này:

  • NextRequest cung cấp thông tin về request hiện tại.
  • NextResponse.redirect() chuyển người dùng sang URL khác.
  • NextResponse.next() cho phép tiếp tục xử lý request.
  • matcher xác định những đường dẫn mà Proxy cần áp dụng.

Đây là ví dụ chuyển hướng đơn giản. Trong nhiều trường hợp, redirect tĩnh có thể được cấu hình trực tiếp trong next.config.ts mà không cần Proxy.

6.2. Proxy có thay thế xác thực và phân quyền không?

Không.

Proxy có thể hỗ trợ kiểm tra sơ bộ và chuyển hướng người dùng, nhưng không nên là lớp bảo mật duy nhất của ứng dụng.

Ví dụ, chuyển người dùng chưa đăng nhập khỏi /dashboard không có nghĩa là dữ liệu quản trị đã được bảo vệ đầy đủ.

Các API, Server Actions và những nơi truy cập dữ liệu nhạy cảm vẫn cần kiểm tra xác thực và quyền truy cập ở phía server. Không được chỉ dựa vào việc ẩn nút hoặc chặn giao diện ở frontend.

7. Phân biệt các file quan trọng trong App Router

File Vai trò
layout.tsx Chia sẻ giao diện giữa các trang
loading.tsx Hiển thị giao diện trong lúc nội dung đang tải
error.tsx Hiển thị giao diện dự phòng khi có lỗi thuộc phạm vi Error Boundary
not-found.tsx Hiển thị giao diện khi không tìm thấy route hoặc tài nguyên
global-error.tsx Xử lý lỗi ở phạm vi Root Layout
proxy.ts Xử lý request trước khi route hoàn tất, như redirect hoặc rewrite

Những file này có tên và vai trò riêng. Next.js nhận diện chúng dựa trên quy ước file, vì vậy bạn không cần tự tạo một cơ chế routing riêng để kích hoạt chúng.

8. Bài tập thực hành

Hãy tiếp tục dự án Next.js của bạn và thực hiện các yêu cầu sau:

  1. Tạo Root Layout chứa cấu trúc HTML cơ bản.
  2. Tạo layout riêng cho khu vực blog.
  3. Tạo loading.tsx hiển thị trạng thái tải bài viết.
  4. Tạo error.tsx với nút thử lại.
  5. Tạo not-found.tsx với liên kết quay về trang chủ.
  6. Thử tạo proxy.ts để chuyển hướng từ một URL cũ sang URL mới.
  7. Kiểm tra rằng việc điều hướng giữa các trang không làm mất những thành phần giao diện dùng chung ngoài dự kiến.

Sau khi hoàn thành, hãy thử chủ động tạo tình huống không tìm thấy dữ liệu và tình huống phát sinh lỗi để kiểm tra giao diện xử lý tương ứng.

9. Kết luận

Layouts giúp tái sử dụng giao diện và tổ chức cấu trúc trang. Loading UI cải thiện phản hồi khi nội dung đang được tải. Error Handling giúp ứng dụng phản ứng có kiểm soát khi xảy ra lỗi, còn not-found.tsx hỗ trợ xử lý những trang hoặc tài nguyên không tồn tại.

Proxy bổ sung khả năng xử lý request trước khi route hoàn tất, nhưng không thay thế cơ chế xác thực và phân quyền ở phía server.

Khi đã nắm được cách tổ chức route và quản lý giao diện theo từng trạng thái, bước tiếp theo là tìm hiểu một trong những khái niệm quan trọng nhất của Next.js: Server Components, Client Components và ranh giới giữa server với client.

Tài liệu tham khảo

Bài viết khác

Series 7 — Web Quality – Engineering :Testing – Unit Testing, Integration Testing, Web Performance – Core Web Vitals, Code Splitting, Lazy Loading

Series 7 — Web Quality – Engineering Bài 3: Testing – Unit Testing, Integration Testing và End-to-End Testing trong ứng dụng web 1. Vì sao ứng dụng web cần Testing? Trong quá trình phát triển Frontend, chúng ta thường kiểm tra ứng dụng bằng cách chạy website trên trình duyệt, nhấn vào các nút, nhập […]

Series 7 — Web Quality – Engineering : Authentication & Authorization

Series 7 — Web Quality – Engineering Bài 1: Authentication & Authorization – Xác thực và phân quyền trong ứng dụng web 1. Mở đầu Khi xây dựng một ứng dụng web có chức năng đăng nhập, chúng ta thường nghĩ rằng chỉ cần tạo biểu mẫu nhập email, mật khẩu và kiểm tra thông […]

Series 6 – Next.js Advanced – Production: Next.js Build & Deployment

Series 6 – Next.js Advanced & Production Bài 5: Next.js Build & Deployment – Từ mã nguồn đến môi trường Production 1. Mở đầu Trong quá trình phát triển một ứng dụng web, việc chạy thành công trên máy tính cá nhân chưa có nghĩa là ứng dụng đã sẵn sàng để đưa đến người […]

Series 6 – Next.js Advanced – Production: Next.js Internationalized Routing Next.js Static Export

Series 6 – Next.js Advanced & Production   Bài 3: Next.js Internationalized Routing – Tổ chức URL cho website đa ngôn ngữ 1. Mở đầu Sau khi xây dựng cơ chế dịch nội dung và định dạng theo locale, ứng dụng cần một cách để người dùng truy cập đúng phiên bản ngôn ngữ. Ví […]

Series 6 – Next.js Advanced & Production: Metadata & SEO, Internationalization (i18n) & Localization (l10n)

Series 6 – Next.js Advanced & Production Bài 1: Metadata & SEO trong Next.js – Tối ưu thông tin và khả năng hiển thị trên công cụ tìm kiếm 1. Mở đầu Khi xây dựng một website, việc hoàn thiện giao diện và chức năng mới chỉ là một phần của quá trình phát triển. […]

Series 5 – Next.js Fundamentals: CSR, SSR, SSG, ISR và cách lựa chọn

Series 5 – Next.js Fundamentals   Bài 7 : CSR, SSR, SSG và ISR – Các chiến lược Rendering trong Next.js 1. Mở đầu Khi xây dựng một website bằng React, chúng ta thường tập trung vào việc tạo component, quản lý state và hiển thị giao diện trên trình duyệt. Tuy nhiên, khi ứng dụng […]

Leave a Reply

Your email address will not be published. Required fields are marked *