11 min read

Next.js 2022: Vẫn Là 'Chân Ái', Nay Còn 'Xịn' Hơn!

Next.js 2022: Vẫn Là 'Chân Ái', Nay Còn 'Xịn' Hơn!

Next.js 2022: “Bình Cũ Rượu Mới”, Ngon Hơn Xưa!

Chào các “đồng code”! 👋 Năm 2021, chúng ta đã “bóc tem” Next.js và “phải lòng” em nó vì những tính năng “đỉnh của chóp” như SSR, SSG, Automatic Routing, phải không nào? Nhưng “cuộc vui” không dừng lại ở đó. Một năm trôi qua, Next.js đã “tiến hóa” với nhiều “vũ khí” mới, hứa hẹn sẽ khiến các lập trình viên front-end “mê mệt”. Bài viết này sẽ “review” nhanh những điểm “nâng cấp” đáng chú ý nhất của Next.js trong năm 2022.

Có Gì “Hot” Trong Phiên Bản Next.js 2022?

Các lập trình viên đã nắm vững những điều cơ bản của Next.js rồi, nhưng phiên bản 2022 vẫn mang đến những điều mới và bất ngờ. Chúng ta cùng đi xem những thuật ngữ trên và thử sức để hiểu rõ hơn về những cải tiến vững chắc này nhé.

1. Incremental Static Regeneration (ISR): “Đỉnh Cao” Của Sự Linh Hoạt! 🚀

Nhớ hồi xưa, khi dùng SSG (Static Site Generation), mỗi lần muốn cập nhật nội dung phải build lại “cả cục” website. “Chậm như rùa” 🐢, đúng không? Nhưng với Incremental Static Regeneration (ISR), Next.js cho phép cập nhật nội dung của các trang static mà không cần phải build lại toàn bộ. “Xịn” chưa?

ISR hoạt động như thế nào?

  • Bạn chỉ định thời gian (tính bằng giây) để revalidate (xác thực lại) trang.
  • Khi hết thời gian đó, request đầu tiên đến trang sẽ kích hoạt quá trình regenerate (tạo lại) trang đó ở background.
  • Trong lúc trang đang được regenerate, Next.js sẽ phục vụ phiên bản cũ (stale) của trang.
  • Khi quá trình regenerate hoàn tất, Next.js sẽ “âm thầm” cập nhật trang mới.

ISR giúp chúng ta có thể xử lý dữ liệu động mà vẫn giữ được hiệu suất của SSG, tạo nên một giải pháp hoàn hảo cho những website cần vừa tĩnh vừa động.

Tại sao nên sử dụng ISR?

Việc chỉ cần cập nhật một số trang nhất định thay vì toàn bộ websites sẽ giúp giảm thời gian xây dựng cũng như tiết kiệm tài nguyên. Điều này thực sự quan trọng khi bạn đang vận hành một trang web lớn với lượng truy cập lớn.

Ví dụ:

// pages/products/[id].tsx

export async function getStaticProps({ params }: { params: { id: string } }) {
  const product = await getProductById(params.id);

  return {
    props: {
      product,
    },
    revalidate: 60, // Revalidate sau mỗi 60 giây
  };
}

export async function getStaticPaths() {
  // fallback: blocking => The user will wait until the page is generated.
  // fallback: true => The user will see the fallback page while the page is being generated.
  // fallback: false => 404 not found.
  return { paths: [], fallback: "blocking" };
}

function ProductPage({ product }: { product: any }) {
  // ... render the product
}

export default ProductPage;

Với revalidate: 60, trang sản phẩm sẽ được tự động cập nhật sau mỗi 60 giây. Quá “tiện”, phải không nào?

Ứng Dụng ISR Trong Thực Tế:

ISR thường được sử dụng trong những trang chứa nội dung tương đối cập nhật thường xuyên nhưng không quá thay đổi mọi phút. Những trang blog cá nhân, ảnh sản phẩm, hoặc tính năng hiển thị dữ liệu thời tiết đều là những ví dụ điển hình về việc sử dụng ISR.

2. Image Optimization: “Auto” Đẹp, “Auto” Nhanh! 🖼️

Next.js đã “xịn” nay còn “xịn” hơn với tính năng tối ưu hóa hình ảnh tự động. Component next/image được “nâng cấp” với khả năng:

  • Resize ảnh tự động dựa trên thiết bị.
  • Chuyển đổi ảnh sang định dạng WebP (nếu trình duyệt hỗ trợ).
  • Lazy loading ảnh.

Chỉ cần dùng component <Image>, khỏi cần config “lằng nhằng”, ảnh của bạn sẽ được “auto” đẹp, “auto” nhẹ, load “auto” nhanh!

Ví dụ:

import Image from "next/image";

function MyComponent() {
  return (
    <Image
      src="/my-awesome-image.jpg" // Next.js sẽ tự động tối ưu hóa hình ảnh này
      alt="My Awesome Image"
      width={500}
      height={300}
      priority // ưu tiên load trước.
      placeholder="blur" // Thêm hiệu ứng làm mờ trong lúc hình ảnh đang load
    />
  );
}

Cách Hoạt Động Của next/image:

  • Lazy Loading: Đây là cơ chế cho phép tải ảnh chỉ khi chúng được nhìn thấy trong viewport, giúp cải thiện thời gian tải trang web.
  • Các Định Dạng Hình Ảnh: Sử dụng định dạng WebP nếu trình duyệt hỗ trợ, đảm bảo kích thước nhẹ gọn hơn và chất lượng tốt hơn so với các định dạng hình ảnh thông thường như JPEG hoặc PNG.
  • Cải Thiện Quy Cách Thay Đổi Kích Thước: Đảm bảo rằng ảnh luôn có kích thước phù hợp với thiết bị người dùng, giúp tối ưu hóa trải nghiệm sử dụng trang web trên các thiết bị di động.

Ưu Điểm Sử Dụng next/image:

  • Giảm đáng kể kích thước file ảnh xuống khiến thời gian tải trang web được cải thiện đáng kể.
  • Tiết kiệm băng thông cho người dùng bởi chỉ cần tải kích thước phù hợp với thiết bị.
  • Tiết kiệm thời gian và công sức trong việc tối ưu hóa hình ảnh, giúp tận dụng tốt hơn vào việc phát triển ứng dụng.

3. Middleware: “Nắm Quyền” Kiểm Soát Request! 🤝

Middleware là một “siêu năng lực” mới của Next.js, cho phép bạn chạy code trước khi một request được xử lý. Bạn có thể dùng Middleware để:

  • Redirect người dùng dựa trên location, cookie, hoặc các header khác.
  • Rewrite URL.
  • Thêm các header bảo mật.
  • A/B testing.

Middleware hoạt động như thế nào?

Middleware hoạt động ở phía serve, điều này giúp kiểm soát tốt hơn quá trình xử lý request mà không làm giảm hiệu suất. Bạn có thể sử dụng JavaScript để tùy chỉnh việc điều hướng, dựa vào yêu cầu của người dùng hoặc bất kỳ điều kiện nào khác.

Ví dụ:

// middleware.ts

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

export function middleware(request: NextRequest) {
  const response = NextResponse.next();

  if (request.nextUrl.pathname.startsWith("/about")) {
    response.headers.set("x-middleware", "about");
  }

  if (request.nextUrl.pathname.startsWith("/dashboard")) {
    response.headers.set("x-middleware", "dashboard");
  }

  return response;
}

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

Middleware giúp bạn kiểm soát request một cách linh hoạt và mạnh mẽ hơn bao giờ hết. “Xịn” quá Next.js ơi!

Ứng Dụng Middleware Trong Thực Tế:

Middleware là một công cụ mạnh mẽ giúp tùy chỉnh các yêu cầu HTTP theo nhiều cách khác nhau như một số ví dụ dưới đây:

  • Redirect người dùng trước khi họ truy cập vào trang bị bảo vệ: Điều này cực kỳ hữu ích để bảo vệ tài nguyên nhạy cảm mà chỉ người dùng đã xác thực mới có thể truy cập.
  • Rewrite URL để đảm bảo tương thích khi truy cập qua nhiều thiết bị: Điều này giúp thống nhất cách các URL được xử lý, giúp giảm tối đa sự bất tiện cho người dùng.
  • Thêm các header bảo mật: Đây là cách nhanh chóng để tăng cường tính bảo mật của trang web, ngăn chặn các cuộc tấn công phổ biến như CORS attacks.
  • A/B Testing: Lựa chọn phiên bản trang web khác nhau dựa trên vị trí địa lý hay nhóm người dùng giúp tối ưu hóa trải nghiệm người dùng thông qua việc thử nghiệm nhiều phiên bản đa dạng.

Cách Tạo Middleware Trong Next.js:

Để tạo Middleware cho một dự án Next.js, bạn chỉ cần tạo một file middleware.js tại thư mục gốc của dự án.

touch middleware.js

Tiếp theo, bạn có thể thêm các hàm tùy chỉnh để xử lý các yêu cầu của Middleware.

export function middleware(request) {
  if (request.nextUrl.pathname.startsWith("/dashboard")) {
    if (!request.cookies.get("authorized")) {
      const url = request.nextUrl.clone();
      url.pathname = "/login";
      return NextResponse.redirect(url);
    }
  }
  return NextResponse.next();
}

Cải Tiến Các Động Tác Khác

4. Automatic Static Optimisation (ASE)

Automatic Static Optimization (ASE) giúp tự động chuyển đổi các trang động thành trang tĩnh. Điều này giúp cải thiện hiệu suất trang web và cũng làm giảm số lượng các yêu cầu đến server. ASE hoạt động tự động nên không cần thiết cấu hình phức tạp.

5. CSS tách các modules

Next.js 2022 giúp các tệp CSS nhỏ gọn hơn thông qua việc dịch các module CSS thành các tệp CSS riêng biệt. Điều này giúp giảm tải băng thông quá trình tải trang.

Ví dụ:

Sử dụng CSS Modules trong một component đơn giản:

import styles from "./Button.module.css";

function Button({ children }) {
  return <button className={styles.button}>{children}</button>;
}

export default Button;

6. Thư viện Next.js Image

Thư viện Next.js Image hỗ trợ tối ưu hóa hình ảnh, giúp giảm kích thước và cải thiện tốc độ tải trang. Bạn chỉ cần sử dụng component Image thay vì thẻ img thông thường của HTML.

Ví dụ:

import Image from "next/image";

function MyComponent() {
  return (
    <div>
      <h1>Chào mừng bạn đến với trang của chúng tôi</h1>
      <Image
        src="/about-us.png"
        alt="Ảnh giới thiệu về chúng tôi"
        width={500}
        height={300}
      />
    </div>
  );
}

Khởi Tạo Dự Án Next.js 2022: Vẫn “Dễ Như Ăn Kẹo” Nhưng…

Cách khởi tạo dự án Next.js về cơ bản vẫn giống như năm 2021:

npx create-next-app@latest my-next-app --typescript
cd my-next-app
npm run dev

Tuy nhiên, bạn sẽ thấy một số thay đổi nhỏ trong project structure, đặc biệt là nếu bạn chọn sử dụng App Router (sẽ nói ở phần sau).

App Router: Một cách định tuyến mới

Từ phiên bản 12 trở đi, Next.js giới thiệu App Router như là giải pháp thay thế cho Pages Router. App Router cung cấp một số tính năng hữu ích hơn như Nested Layouts, Parallel Routes, và hơn thế nữa.

Ưu điểm của App Router khi so với Pages Router:

  • Nested Layouts giúp tổ chức code tốt hơn, dễ dàng quản lý layout giữa các trang.
  • Parallel Routes cho phép hiển thị nhiều trang cùng một lúc trên một URL cụ thể.
  • File-based Routing tự động quét các file trong thư mục app để xác định các route.

Ví dụ về cấu trúc thư mục sử dụng App Router:

app/
├── about/
│   ├── page.tsx      // /about
│   └── layout.tsx   // Layout cho /about
├── blog/
│   ├── [slug]/       // Tùy chỉnh route theo slug
│   │   └── page.tsx  // /blog/[slug]
│   └── layout.tsx   // Layout cho /blog
├── (auth)/
│   ├── layout.tsx    // Layout cho nhóm (auth)
│   ├── login/
│   │   └── page.tsx  // /login
│   └── register/
│       └── page.tsx  // /register
├── (shop)/
│   ├── cart/
│   │   └── page.tsx  // /(shop)/cart
│   └── checkout/
│       └── page.tsx  // /(shop)/checkout
├── components        // Các component dùng chung
├── lib               // Các hàm tiện ích
└── types             // Định nghĩa kiểu dữ liệu

Cách dùng Layouts trong App Router:

// app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div>
      <h1>Dashboard</h1>
      {/* Sidebar, header, etc. */}
      <section>{children}</section>
    </div>
  );
}

Kết Luận: Next.js “Vẫn Đỉnh”, “Vẫn Chất”!

Next.js tiếp tục khẳng định vị thế là một framework “đỉnh cao” cho các lập trình viên front-end. Với những cải tiến vượt bậc trong năm 2022, Next.js giúp cho việc phát triển web app trở nên nhanh hơn, mượt hơn và “xịn” hơn. Nếu bạn chưa “thử sức” với Next.js, hãy “mạnh dạn” “nhảy hố” ngay hôm nay! Đảm bảo bạn sẽ không hối hận đâu! 😉

Những Gợi Ý Khác

Webpack 5: Next.js 2022 sử dụng Webpack 5 để cải thiện hiệu suất xây dựng cũng như hỗ trợ nhiều bỏ lọc mới.

Automatic Static Optimization (ASE): Tính năng này giúp tự động chuyển đổi các trang động thành trang tĩnh để tăng hiệu suất.

Fallback ISR: Khi sử dụng ISR, bạn có thể dựa vào chế độ fallback để phục vụ phiên bản cũ của trang trong quá trình revalidate.

Build improvements: Cải tiến quá trình xây dựng giúp giảm thời gian chờ đợi khi thực hiện các thay đổi.

Tài Liệu Tham Khảo:

Chúc các bạn có một kỳ nghỉ hè thật relax và đầy ý nghĩa! 🎉🌞