+2

Giới thiệu về NextJS

Giới thiệu

nextjs-logo.png

Next.js là một framework phổ biến trong việc phát triển ứng dụng web dựa trên React và được phát triển bởi Vercel. Được giới thiệu lần đầu tiên vào năm 2016, Next.js cung cấp một nền tảng mạnh mẽ và linh hoạt để phát triển các ứng dụng React tối ưu hóa hiệu suất và thân thiện với công cụ tìm kiếm (SEO). Nhờ vào khả năng kết hợp tính năng server-side rendering (SSR) và static site generation (SSG), Next.js đã trở thành một lựa chọn hàng đầu của các lập trình viên khi xây dựng các ứng dụng web hiện đại.

Next.js có sẵn những tính năng và tự động cấu hình các công cụ cần thiết cho React như bundling, compiling, ... giúp lập trình viên tận dụng và tập trung vào việc phát triển ứng dụng một cách nhanh chóng và tối ưu thay vì mất thời gian vào việc cấu hình.

Tính năng chính của Next.js

Rendering

Next.js hỗ trợ nhiều phương thức render, giúp tăng cường hiệu suất, SEO và trải nghiệm người dùng. Các phương thức render trong Next.js bao gồm Static Generation (SSG), Server-Side Rendering (SSR), Incremental Static Regeneration (ISR)Client-Side Rendering (CSR). Mỗi phương thức đều có ưu, nhược điểm riêng và phù hợp với những trường hợp sử dụng khác nhau. Để hiểu rõ hơn về những phương thức này ta cùng tìm hiểu phía bên dưới.

Static Site Generation (SSG)

static-generation.png

Static Generation là phương thức render phổ biến trong Next.js, trong đó HTML của trang được tạo ra tại thời điểm build, sau đó sẽ được lưu và phục vụ dưới dạng tĩnh cho các yêu cầu người dùng. Đây là phương thức render hiệu quả nhất về hiệu suất vì trang đã được chuẩn bị sẵn trước khi người dùng truy cập. Với Next.js, bạn có thể dễ dàng áp dụng SSG bằng cách sử dụng hàm getStaticProps, hàm này sẽ lấy dữ liệu tại thời điểm build và chuyển vào component dưới dạng props.

Ưu điểm:

  • Hiệu năng cao: Do HTML được chuẩn bị sẵn, tốc độ tải trang rất nhanh.
  • SEO tốt: HTML có sẵn ngay từ đầu, dễ dàng được các công cụ tìm kiếm thu thập thông tin.
  • Chi phí thấp: Giảm tải cho máy chủ vì không cần xử lý thêm khi có người dùng truy cập.

Nhược điểm:

  • Hạn chế thay đổi nội dung: Phương thức này chỉ phù hợp với trường hợp nội dung không thay đổi thường xuyên, còn với nội dung thay đổi liên tục sẽ cần phương thức khác.

SSG phù hợp với các trang có nội dung cố định(tĩnh) như trang giới thiệu sản phẩm (landing page), trang blog, ... hoặc các trang không yêu cầu cập nhật thông tin thường xuyên.

Server-side Rendering (SSR)

server-side-rendering.png

Server-Side Rendering là phương thức render mà trang được tạo tại thời điểm có yêu cầu truy cập. Khi người dùng truy cập trang, máy chủ sẽ tạo HTML với dữ liệu mới nhất và gửi về cho trình duyệt. Điều này giúp cập nhật nội dung theo dữ liệu mới nhất, nhưng cũng tiêu tốn tài nguyên máy chủ. Trong Next.js, SSR có thể được thực hiện thông qua hàm getServerSideProps, hàm này lấy dữ liệu mỗi lần có yêu cầu và chuyển vào component, tạo ra trang được render ngay trên máy chủ.

Ưu điểm:

  • Cập nhật nội dung động: Nội dung luôn cập nhật mới nhất theo mỗi yêu cầu truy cập.
  • SEO tốt: HTML được render từ máy chủ nên dễ thu thập thông tin.

Nhược điểm:

  • Hiệu suất kém hơn SSG: Do trang phải render mỗi khi có yêu cầu, nên mất thời gian xử lý.
  • Chi phí cao hơn: Tăng tải cho máy chủ nếu có lượng truy cập lớn.

SSR thích hợp với các trang có dữ liệu thay đổi liên tục như trang thương mại điện tử, mạng xã hội, tin tức, bảng xếp hạng, ... hoặc các trang đòi hỏi tính cá nhân hoá cao.

Incremental Static Regeneration (ISR)

incremental-static-regeneration-nextjs-1024x565.png

Incremental Static Regeneration là một trong những tính năng tiên tiến của Next.js, nó phương pháp tối ưu hóa giữa SSG và SSR. ISR cho phép tạo lại các trang tĩnh sau một khoảng thời gian nhất định (thông qua thuộc tính revalidate) mà không cần build lại toàn bộ ứng dụng. Điều này giúp trang vừa có hiệu suất cao như SSG, vừa có khả năng cập nhật nội dung thường xuyên. Với Next.js bằng cách sử dụng thuộc tính revalidate trong hàm getStaticProps, các trang có thể được tạo lại trên máy chủ mà không làm ảnh hưởng đến trải nghiệm người dùng.

Ưu điểm:

  • Hiệu suất cao: Trang có thể lưu trữ tĩnh nhưng vẫn tự động cập nhật.
  • Cập nhật định kỳ: Dễ dàng điều chỉnh thời gian tái tạo trang phù hợp.

Nhược điểm:

  • Độ trễ cập nhật dữ liệu: nếu nội dung trên trang cần cập nhật ngay lập tức khi có sự thay đổi, ISR có thể gây ra độ trễ, dẫn đến việc hiển thị dữ liệu lỗi thời cho người dùng trong một thời gian nhất định.

ISR đặc biệt lý tưởng với các trang có dữ liệu thay đổi vừa phải, chẳng hạn trang tin tức hoặc trang blog yêu cầu cập nhật nội dung một cách đều đặn nhưng không quá thường xuyên.

Client-Side Rendering (CSR)

Zi_gXN3JpQ5PTP9S_CSR.png

Client-Side Rendering là phương thức render truyền thống của React, trong đó nội dung trang sẽ được render từ phía người dùng sau khi tải lên. Next.js cũng hỗ trợ CSR cho các trang không yêu cầu SEO mạnh.

Ưu điểm:

  • Tương tác linh hoạt: Dễ dàng cập nhật dữ liệu, đặc biệt phù hợp với các ứng dụng có nhiều tương tác người dùng.
  • Giảm tải cho máy chủ: Máy chủ chỉ gửi dữ liệu cần thiết, client sẽ xử lý render.

Nhược điểm:

  • Hiệu suất tải trang ban đầu thấp: Trang ban đầu sẽ chỉ có HTML trống, nội dung chỉ hiển thị sau khi JavaScript được thực thi.
  • SEO: Vì nội dung hiển thị trễ nên không thân thiện với các công cụ tìm kiếm.

CSR phù hợp với các ứng dụng không đòi hỏi SEO như các ứng dụng đơn trang phức tạp (SPA), ứng dụng nội bộ hoặc trang quản trị.

Routing

partial-rendering.png

Next.js cung cấp hệ thống routing (định tuyến) linh hoạt và dễ sử dụng. Next.js áp dụng cơ chế routing theo file-based routing (định tuyến theo tệp tin), giúp đơn giản hóa việc xây dựng và quản lý các tuyến đường (route) trong ứng dụng. Bên cạnh đó, Next.js cũng hỗ trợ các phương pháp định tuyến dynamic routing, nested routing, API routes để đáp ứng các nhu cầu phức tạp hơn. Ta cùng tìm hiểu, phân tích về các loại routing trong Next.js và cách chúng hoạt động phía bên dưới.

File-based Routing

File-based Routing là routing cơ bản trong Next.js. Nó sử dụng cấu trúc thư mục để tự động tạo các tuyến đường cho ứng dụng. Tất cả các file nằm trong thư mục /pages sẽ tự động trở thành một route tương ứng, không cần cấu hình thêm.

Ví dụ, một file pages/viblo.js sẽ được render khi người dùng truy cập đường dẫn /viblo. Tương tự, một file pages/viblo/post.js sẽ tạo đường dẫn viblo/post. Điều này giúp quản lý các route trở nên dễ dàng, hiệu quả và loại bỏ sự phức tạp khi phải cấu hình định tuyến như trong các ứng dụng React truyền thống, nơi thường phải sử dụng thư viện react-router.

Ưu điểm:

  • Dễ sử dụng: Tạo và quản lý route trực tiếp bằng cách tạo các file và thư mục.
  • Đồng nhất và trực quan: Cấu trúc thư mục phản ánh cấu trúc định tuyến, dễ theo dõi và kiểm soát.

Nhược điểm:

  • Giới hạn với ứng dụng phức tạp: Khi có nhiều route phức tạp, file-based routing có thể thiếu linh hoạt, đòi hỏi nhiều thư mục lồng nhau.

Dynamic Routing

Next.js cho phép định tuyến động (Dynamic Routing) thông qua các thư mục hoặc file có tên động bằng cách sử dụng cú pháp dynamic segments ([param]). Điều này rất hữu ích khi tạo ra các đường dẫn thay đổi linh hoạt, ví dụ như các trang sản phẩm, bài viết hoặc hồ sơ người dùng.

Ví dụ một file pages/post/[id].js sẽ tạo đường dẫn /post/123, với 123 là ID sản phẩm được lấy từ URL. Hay file pages/post/[slug].js sẽ tạo đường dẫn /post/dynamic-routing, với dynamic-routing đại diện cho giá trị slug. Điều này mang lại sự linh hoạt cao, đặc biệt cho các ứng dụng co lượng lớn nội dung không xác định trước.

Ưu điểm:

  • Dễ dàng tùy chỉnh các route động: Đáp ứng nhanh chóng các yêu cầu về route động như profile người dùng, sản phẩm, bài viết, ...
  • Tích hợp tốt với API: Next.js hỗ trợ getStaticPathsgetStaticProps, cho phép tạo các trang động mà vẫn tối ưu hóa hiệu suất thông qua phương thức Static Generation.

Nhược điểm:

  • Độ phức tạp tăng theo cấu trúc: Khi có nhiều cấp độ route động, ứng dụng có thể trở nên khó quản lý.

Nested Routing

Next.js không hỗ trợ nested routing một cách trực tiếp như một số framework khác. Thay vào đó, nested routing có thể được thiết lập bằng cách tạo ra các thư mục lồng nhau trong /pages, mỗi một thư mục con sẽ đại diện cho một cấp route mới hoặc sử dụng React components để xây dựng giao diện lồng nhau theo mong muốn.

Ví dụ file pages/post/[slug]/comments.js sẽ dẫn đến đường dẫn /post/post-title/comments. Hoặc sử dụng các component như Header hoặc Sidebar trong file pages/post/[slug]/index.js để hiển thị cấu trúc giao diện lồng nhau.

Ưu điểm:

  • Tạo cấu trúc trang rõ ràng: Dễ dàng phân chia các thành phần giao diện thành từng phần riêng biệt.
  • Tái sử dụng và tùy chỉnh giao diện: Component lồng nhau giúp xây dựng giao diện đa cấp dễ quản lý.

Nhược điểm:

  • Thiếu hỗ trợ native cho nested routing: do các route được ánh xạ trực tiếp từ cấu trúc thư mục nên sẽ bị hạn chế việc tổ chức cấu trúc route phức tạp, nhất là khi ứng dụng lớn dần và cần nhiều cấp route.
  • Khó khăn quản lý layout cho các route lồng nhau: Do không có cấu trúc layout lồng nhau mặc định nên đòi hỏi sử dụng các biện pháp thủ công như tạo nhiều component layou hoặc sử dụng App, ... để quản lý layout làm cho mã nguồn trở nên phức tạp và khó bảo trì.

API Routing

Next.js còn cung cấp khả năng tạo các API route, hoạt động như một API server tích hợp trong ứng dụng mà không cần đến server back-end riêng biệt. Các API route này được tạo ra bằng cách thêm các file vào thư mục /pages/api và sẽ tạo thành các endpoint RESTful tương ứng, có thể xử lý các yêu cầu HTTP như GET, POST, PUT và DELETE. Đây là một tính năng riêng biệt tiện dụng để xây dựng các API nhỏ.

Ví dụ filepages/api/user.js sẽ tạo API route /api/user để xử lý yêu cầu từ phía client. API route này hữu ích khi muốn tạo các endpoint phục vụ các thao tác như gửi email, xử lý dữ liệu từ form hoặc tương tác với các API bên ngoài mà không cần một server backend riêng biệt.

Ưu điểm:

  • Tích hợp dễ dàng: Xây dựng các API route mà không cần backend server riêng.
  • Bảo mật và hiệu suất cao: API route có thể bảo vệ thông tin nhạy cảm vì chỉ được thực thi phía máy chủ.

Nhược điểm:

  • Giới hạn về độ phức tạp: API route chỉ phù hợp với các yêu cầu đơn giản, cho các ứng dụng phức tạp sẽ cần giải pháp API khác như sử dụng server riêng.

Styling

Next.js hỗ trợ nhiều phương pháp styling linh hoạt, giúp các nhà phát triển dễ dàng thiết kế giao diện và tối ưu hóa ứng dụng. Styling trong Next.js bao gồm nhiều option từ CSS Modules, Styled JSX, CSS-in-JS, CSS Frameworks đến Tailwind CSSSass/SCSS. Mỗi phương pháp đều có ưu, nhược điểm và đáp ứng nhiều nhu cầu khác nhau trong quá trình phát triển. Ta sẽ cùng tìm hiểu một vài kiểu styling trong Next.js phía bên dưới.

CSS Modules

CSS Modules là một tính năng có sẵn trong Next.js, cho phép tạo các kiểu CSS phạm vi cục bộ (local scoped) cho từng component hoặc trang. Mỗi CSS class khi sử dụng CSS Modules đều được tự động tạo ra một tên duy nhất, tránh xung đột và không cần phải sử dụng các quy ước đặt tên phức tạp.

Cách dùng:

  • Để sử dụng CSS Modules, chỉ cần đặt file CSS có đuôi là .module.css (ví dụ: styles/Home.module.css).
  • Import CSS Modules vào component và sử dụng CSS như một đối tượng JavaScript.

Ưu điểm:

  • Phạm vi cục bộ: Mỗi class được scope riêng cho từng module, tránh xung đột tên.
  • Dễ đọc và bảo trì: Tên class ngắn gọn và không bị trùng lặp.

Nhược điểm:

  • Không hỗ trợ tính năng JavaScript trong CSS: CSS Modules thiếu khả năng tùy chỉnh động như CSS-in-JS.

=> CSS Modules phù hợp cho các dự án nhỏ hoặc các trang mà phong cách không cần quá phức tạp.

Styled JSX

Styled JSX là một giải pháp CSS-in-JS có sẵn trong Next.js, giúp nhúng trực tiếp CSS vào trong code của component. Styled JSX tạo ra CSS riêng cho từng component và đảm bảo CSS này không bị ảnh hưởng bởi các component khác.

Cách dùng:

  • Viết CSS trong thẻ <style jsx> bên trong component.
function Greet() {
  return (
    <div className="container">
      <h1>Hello Next.js</h1>
      <p>Let's explore different ways to style Next.js apps</p>
      <style jsx>{`
        .container {
          margin: 50px;
        }
        p {
          color: black;
        }
      `}</style>
    </div>
  );
}
 
export default Greet;

Ưu điểm:

  • Cục bộ hoá CSS: CSS chỉ áp dụng cho component đó, hạn chế xung đột.
  • Dễ dàng tái sử dụng và quản lý: Tất cả kiểu được viết cùng với logic của component, dễ quản lý.
  • Tích hợp sẵn trong Next.js: Không cần cài đặt thêm thư viện bên ngoài.

Nhược điểm:

  • Phức tạp khi cần mở rộng: Viết CSS cho các component phức tạp có thể gây khó quản lý và thiếu tính linh hoạt.

=> Styled JSX phù hợp cho các ứng dụng Next.js nhỏ hoặc những component có phong cách độc lập, không tái sử dụng nhiều.

CSS-in-JS

Ngoài Styled JSX, Next.js cũng hỗ trợ các thư viện CSS-in-JS phổ biến như styled-components, emotion, ant-design, chakra-ui, ...** CSS-in-JS** là phương pháp viết CSS trực tiếp trong JavaScript, kết hợp sức mạnh của CSS với tính năng lập trình linh hoạt của JavaScript, tạo ra khả năng styling động và dễ quản lý.

Cách đơn giản nhất sử dụng CSS-in-JS là sử dụng inline style.

function Greet() {
  return <p style={{ color: 'black' }}>Greet</p>
}
 
export default Greet

Ưu điểm:

  • Styling động: CSS-in-JS cho phép áp dụng logic JavaScript vào CSS, dễ dàng tạo kiểu phụ thuộc vào state, props hoặc context.
  • Quản lý kiểu linh hoạt: Có thể tái sử dụng các styled-component trong toàn bộ ứng dụng.
  • Phạm vi cục bộ tự động: CSS tự động scope cho từng component, tránh xung đột.

Nhược điểm:

  • Hiệu suất: CSS-in-JS có thể ảnh hưởng đến hiệu suất khi chạy ở client-side, do CSS được xử lý động khi render.
  • Kích thước bundle lớn hơn: Thêm thư viện CSS-in-JS có thể tăng kích thước bundle.

=> CSS-in-JS phù hợp với các ứng dụng có phong cách phức tạp, yêu cầu nhiều kiểu động hoặc tái sử dụng các component nhiều lần.

CSS Frameworks

Next.js cũng hỗ trợ các CSS Frameworks phổ biến như Bootstrap, Bulma, Tailwind CSS, ... Trong đó, Tailwind CSS là một framework CSS utility-first được nhiều nhà phát triển Next.js yêu thích, với hệ thống các lớp tiện ích giúp xây dựng giao diện nhanh chóng mà không cần viết nhiều CSS tùy chỉnh.

Cách dùng:

  • Cài đặt các framework CSS qua npm (package manager) và import vào để sử dụng.

Ưu điểm:

  • Tốc độ phát triển nhanh: Các class, component có sẵn giúp thiết kế giao diện nhanh chóng.
  • Giao diện nhất quán: Sử dụng sẵn class, component nên các giao diện thường có phong cách nhất quán.
  • Đáp ứng tốt trên thiết bị di động: Framework CSS cung cấp sẵn các lớp responsive, giúp tối ưu hóa giao diện trên các thiết bị khác nhau.

Nhược điểm:

  • Hạn chế tuỳ chỉnh: Các lớp tiện ích có thể giới hạn khi cần tạo giao diện độc đáo.
  • Kích thước bundle: Một số framework như Bootstrap có thể thêm nhiều code không sử dụng, ảnh hưởng đến hiệu suất.

CSS Frameworks phù hợp cho các ứng dụng cần giao diện cơ bản và triển khai nhanh hoặc yêu cầu sự nhất quán cao trong thiết kế.

Other

Ngoài các tính năng kể trên Next.js còn có các tính năng chính khác với đầy đủ hỗ trợ: Data Fetching, Optimizations, TypeScript. Nhưng do nội dung bài viết cũng khá dài rồi nên mình xin phép hẹn gặp lại các bạn đọc ở một bài viết khác (part2). Các bạn có thể tìm hiểu những nội dung này ở trong chính docs của Next.js

Lời kết

Qua bài viết này mình và các bạn đã cùng tìm hiểu về khái niệm, một số tính năng chính trong Next.js. Mình cũng chỉ là đứa gà mờ lọ mọ học về Next.js nên những kiến thức trên được mình tìm hiểu và học từ nhiều nguồn khác nhau nếu có sai sót gì mong mọi người có thể góp ý để bài viết hoàn thiện hơn. Hy vọng qua bài viết này giúp các bạn có cái nhìn cơ bản về Next.js hoặc là giúp bạn có hứng thú với framework này và bắt tay vào học hòi, tìm tòi và áp dụng nó vào chính công việc hay dự án của mình. Cảm ơn các bạn đã theo dõi đến hết bài viết ❤️.

Tham khảo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí