Những thứ mới mẻ trong Next.js 13

Chào các bạn, trong thời gian vừa qua, dự án của mình có 1 task liên quan đến upgrade version của ứng dụng Next.js đang sử dụng. Cụ thể, dự án hiện tại của mình  đang sử dụng Next.js version 12. Sau một thời gian cân nhắc, các sếp quyết định nâng cấp version lên bản mới nhất là Next.js version 13. Mình thì không trực tiếp được giao phó cho task này nhưng mình cũng tìm hiểu sơ qua về các cải tiến cũng như thay đổi để có thể implement các task trong tương lai. Mình xin mạo muội chia sẻ với các bạn trong bài blog này.

Mặc dù Next.js 13 đã ra mắt được hơn 1 năm (cụ thể ngày 26/10/2022). Nhưng nó vẫn đang là phiên bản latest với một sự ổn định tuyệt vời, cùng những tính năng vượt trội.

Đầu tiên mà là về một cải tiến cho Next/link mà bạn có thể hiện đang sử dụng và cũng là 1 trong những tính năng giúp bạn tối ưu SEO. Cơ bản, tính năng Next/link cho phép chúng ta không cần phải sử dụng thẻ <a> trong một Link component.

Tại sao quan trọng? Trước đây, bạn thường phải thêm thẻ mở rộng <a> như một biện pháp tạm thời để làm cho các liên kết phù hợp với SEO, như sau:

Nhưng tính năng mới của Next/link này cho phép các liên kết hoạt động mà không cần phải thêm nó, giúp chúng ta có được một sự thay đổi đáng giá mang tính "cải thiện chất lượng cuộc sống" :D.

import Link from 'next/link'

// Next.js 12 
<Link href="/about">
  <a>About</a>
</Link>
Link của Next.js 12
import Link from 'next/link'

// Next.js 13 
<Link href="/about">
  About
</Link>
Link của Next.js 13


Tuy là một điều nhỏ nhặt nhưng nó cũng giúp cho tay của bạn đỡ mỏi hơn 😃. Ngoài ra, cũng có thể để cho code của bạn dễ nhìn hơn nữa.

Next/image

Nếu bạn đã sử dụng phiên bản của Next.js 13, thì bạn đã nhận ra việc thời gian tải trang của bạn nhanh hơn, điểm Core Web Vital cao hơn và trải nghiệm người dùng cải thiện, tất cả đều nhờ cách Next.js hiện tại xử lý việc tải hình ảnh.

Thời gian tải nhanh hơn luôn là điều tuyệt vời. Và với điều đó trong tâm trí, Next.js 13 đang đưa điều đó một bước xa hơn với tính năng mới Next/image.

Next.js 13 giới thiệu một component Image mới mạnh mẽ, cho phép bạn dễ dàng hiển thị hình ảnh mà không gây thay đổi bố cục và tối ưu hóa các tệp theo yêu cầu để tăng hiệu suất.

import Image from 'next/image';
import avatar from './lee.png';
 
export default function Home() {
  // "alt" is now required for improved accessibility
  // optional: image files can be colocated inside the app/ directory
  return <Image alt="leeerob" src={avatar} placeholder="blur" />;
}

Trong cuộc khảo sát trong Next.js Comunity, 70% người tham gia cho biết họ đã sử dụng Image componnent mới của Next.js trong production và đã thấy cải thiện về Core Web Vitals. Với Next.js 13, họ đang cải thiện next/image thêm nữa.

Component Image mới:

  • Giảm code JavaScript phía client
  • Dễ dàng tùy chỉnh và cấu hình hơn
  • Dễ access hơn với việc yêu cầu thẻ alt theo mặc định
  • Tương thích với nền tảng Web
  • Tải nhanh hơn vì việc lazy load không yêu cầu hydration

Tất cả điều này đơn giản là bạn sẽ cần ít thời gian hơn để chờ các phần tử tải lên và ít sự di chuyển của chúng trong quá trình xây dựng trang web.

Hơn thế nữa, vì Core Web Vitals đang trở thành một yếu tố xếp hạng quan trọng hơn trong SEO, điều này có nghĩa là chúng ta có thể cải thiện trải nghiệm người dùng và tăng lượng truy cập tiềm năng cho một tính năng có lợi cả hai bên!

Turbopack (alpha)


Turbopack là một công cụ đóng gói tăng cường được tối ưu hóa cho JavaScript và TypeScript, được viết bằng Rust.

Là một tính năng khác được thiết kế để cải thiện trải nghiệm người dùng cũng như tối ưu hóa và cải thiện ứng dụng của bạn. Turbopack là phiên bản kế nhiệm dựa trên Rust của Webpack, và nó rất nhanh chóng trong việc tải ứng dụng với số lượng module lớn.

Next.js liên tục cải thiện tốc độ tải, nhưng với sự tập trung vào việc native bundling, nó có thể tải ứng dụng có 3.000 module trong 1,8 giây, khác biệt đáng kể so với Next.js 12 với 6,3 giây.

So sánh lại với Vite hoặc Webpack, bạn sẽ thấy nhanh hơn 700 lần so với Webpack và nhanh hơn 10 lần so với Vite! Thật đáng kinh ngạc phải không nào :D.

Turpoback đạt được tốc độ này nhờ kiến trúc của nó và việc lưu trữ, nên nó sẽ không bao giờ phải làm công việc tương tự hai lần. Điều này có nghĩa là nó chỉ chạy lại nếu các hàm thay đổi, cho phép bạn bỏ qua nhiều thời gian chạy.

Không có sự khác biệt đáng kể đối với end-user về mặt giao diện, nhưng sẽ có sự khác biệt rất rõ rệt về thời gian build/tải. :D

Note: Turbopack trong Next.js đang ở giai đoạn alpha nên chỉ hỗ trợ next dev. Rất nhiều tính năng mới đang được phát triển. Cùng chờ đợi nhé!

Thư mục app (beta)

Nếu bạn đang sử dụng Next.js phiên bản cũ, thì có lẽ bạn thường xuyên sử dụng thư mục pages để tạo các trang, routes cho ứng dụng.

Tuy nhiên, trong Next.js 13, chúng ta có một thư mục ứng dụng mới mà chúng ta có thể sử dụng thay thế, đó là app

Thư mục page của Next 12 so sánh với Next 13

Bạn có thể thêm thư mục này bằng cách vào next.config.js, sau đó thêm vào:

experimental: { appDir: true }

Note: Tuy nhiên, đây là thử nghiệm nên không khuyến nghị sử dụng cho ứng dụng production. Các bạn tạm thời nên trải nghiệm sự thú vị của nó cho đến khi bản stable ra mắt nhé.

Thư mục mới này cung cấp hỗ trợ cho:

  • Layouts
  • Server components
  • Streaming
  • Async Data Fetching (Truy xuất Dữ liệu Bất Đồng Bộ)

Hãy cùng đi vào chi tiết từng phần nhé.

Layouts

Bố cục đã được cải thiện với Next.js 12, nhưng sẽ được định tuyến khác biệt ở Next.js 13.

Cải thiện layouts và routing là một sự thay đổi "cải thiện chất lượng cuộc sống" khác  với cải thiện tốc độ và thời gian tải trang web. Sự thay đổi chính ở đây liên quan đến kiến trúc layout, cho phép chúng ta lồng bố cục và đặt code ứng dụng cùng nơi.

Để thử nghiệm điều này, sau khi bạn đã set experimental: { appDir: true }, bạn chỉ cần tạo một tệp page.js bên trong thư mục ứng dụng: app/page.js.

// This file maps to the index route (/)
export default function Page() {
  return <h1>Hello, Next.js!</h1>;
}

Sau đó, bạn có thể xác định bố cục thông qua files system. Layouts chia sẻ UI giữa nhiều trang. Khi điều hướng, các bố cục bảo tồn trạng thái, vẫn tương tác và không thực hiện việc render lại.

app/blog/layout.js:

export default function BlogLayout({ children }) {
  return <section>{children}</section>;
}

Nghe có vẻ phức tạp nhưng cơ bản là tất cả hoạt động cùng nhau để duy trì state qua mỗi lần điều hướng, tránh việc render lại và cải thiện thời gian tải.

Server components

Thư mục app mới cũng hỗ trợ kiến trúc server side mới của React, điều này có nghĩa là chúng ta có thể cải thiện tốc độ tải bằng cách loại bỏ các thành phần không cần thiết khỏi trình duyệt phía client:

Thay vào đó, chúng sẽ được load nhiều hơn ở phần server side, ít hơn bên phần front end .

Cách này, phía máy khách có thể được cải thiện và được lưu trữ để luôn tải trang với 1 kích thước có thể dự đoán được, và càng tốt hơn, nó không tăng lên khi ứng dụng phát triển và mở rộng.

Streaming

Một cải thiện về tốc độ và trải nghiệm người dùng khác. Với Streaming, bạn có thể cải thiện thời gian tải bằng cách ngay lập tức hiển thị các phần của trang mà đã được lưu trữ hoặc không cần cập nhật, và sau đó tải các phần của trang đang lấy dữ liệu mới.

Ví dụ: Các nội dung tĩnh trên trang blog, sidebar,...

Không quan trọng bạn sử dụng nó để làm gì. Streaming sẽ giúp bạn cải thiện thời gian tải trang!

Async Data Fetching

Cuối cùng, chúng ta có một sự thay đổi  chất lượng  khác với việc cập nhật cả việc truy xuất dữ liệu và xử lý Promise với các components.

async function getData() {
  const res = await fetch('https://api.example.com/...');
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.
  return res.json();
}
 
// This is an async Server Component
export default async function Page() {
  const data = await getData();
 
  return <main>{/* ... */}</main>;
}

Không chỉ việc cập nhật mới giúp bạn truy xuất dữ liệu một cách không trùng lặp, nó còn cho phép bạn sử dụng một cách đơn giản để truy xuất, lưu trữ và xác nhận lại dữ liệu.

Nói 1 cách đơn giản hơn, bây giờ chúng ta có thể sử dụng Static Site Generation (SSG), Server-Side Rendering (SSR) và Incremental Static Regeneration (ISR) tất cả từ cùng một API, cũng như truy xuất dữ liệu từ bên trong trang và các thành phần!

// This request should be cached until manually invalidated.
// Similar to `getStaticProps`.
// `force-cache` is the default and can be omitted.
fetch(URL, { cache: 'force-cache' });
 
// This request should be refetched on every request.
// Similar to `getServerSideProps`.
fetch(URL, { cache: 'no-store' });
 
// This request should be cached with a lifetime of 10 seconds.
// Similar to `getStaticProps` with the `revalidate` option.
fetch(URL, { next: { revalidate: 10 } });

Kết luận

Trên đây chỉ là một vài feature trong rất nhiều thứ mới đã được thêm vào và cải thiện trong Next.js 13. Để biết thêm thông tin chi tiết, các bạn hãy truy cập vào trang chủ của Next.js nhé. Hy vọng các bạn đã có được cái nhìn tổng quát về những thứ mới trong Next.js 13 để cân nhắc nó cho ứng dụng của bạn. :D Hẹn gặp lại các bạn trong những blog tiếp theo!

References

https://www.smashingmagazine.com/2022/11/whats-new-nextjs-13/

https://nextjs.org/blog/next-13

https://vercel.com/blog/turbopack

https://kulkarniankita.com/react/react-server-client-components