Pre-rendering and Data Fetching in Next.js

Peekaboo, What’s up!!!

Hi! Bài viết này mình sẽ nói về Pre-rendering và Data Fetching trong Next.js

1. Pre-rendering là gì?

Theo mặc dịnh, Next.js hiển thị trước mỗi trang. Điều này có nghĩa là Next.js tạo HTML trước cho từng trang, thay vì để JavaScript  phía máy khách thực hiện tất cả (React). Kết xuất trước có thể mang lại hiệu suất và SEO tốt hơn.

Next.js có hai hình thức pre-rendering: Static Generation and Server-side Rendering. Sự khác biệt nằm ở thời điểm nó tạo HTML cho một trang.

– Static Generation: HTML sẽ được generate tất cả ngay từ đầu và được sử dụng mỗi lần request.
Server-side Rendering: HTML sẽ được generate mỗi lần request.

2. Static Site Generation (SSG)

– Là phương thức Pre-rendering mà khi đó HTML sẽ được tạo ra lúc build time (tạo ra ngay từ đầu).
– Là phương thức được Next.js đề xuất sử dụng.
– Trang web của chúng ta được lưu trữ trong bộ nhớ cache vởi CDN và được cung cấp cho người dùng gần như tức thì.
– Phù hợp với các website: blog, docs, marketing, sản phẩm thương mại điện tử, …

2.1 Static Generation không có Data

– Đối với trường hợp page được tạo mà không cần lấy data từ bên ngoài (API, file system, …), các trang sẽ được generate ngay từ lúc build time.

2.2. Static Generation với Data

– Không phải lúc nào mà các page chúng ta cũng chỉ có HTML. Một số page yêu cầu tìm nạp dữ liệu bên ngoài để hiển thị trước.

– Có hai tình huống và một hoặc cả hai có thể áp dụng:

  1. Nội dung trang của bạn phụ thuộc và dữ liệu bên ngoài: sử dụng getStaticProps.
  2. Đường dẫn trang của bạn phụ thuộc và dữ liệu bên ngoài: Sử dụng getStaticPaths (thường là ngoài  getStaticProps).

Nội dung trang của bạn phụ thuộc vào dữ liệu bên ngoài

– Nó hoạt động cũng khá đơn giản, khi bạn export 1 page component, bạn cũng có thể export 1  async function gọi là getStaticProps:

  • getStaticProps sẽ chạy lúc build time.
  • Ở trong function này bạn có thể gọi đến API bên thứ 3 để lấy data.

– Cấu trúc nó sẽ trông như này:

– Đại khái chúng ta có thể ngầm hiểu rằng đoạn code này sẽ là getStaticProps nói với Next.js rằng: “Này! Page này có 1 số data lầy từ bên ngoài, khi bạn pre-render lúc build-time, bạn hãy xử lý để mà trang Blog kia lấy được sử dụng nhé!”

Ví dụ hoàn chỉnh: Ở đây mình tạo 1 file  pages/index.tsx, trong đó mình sẽ call API để lấy data ở trong function getStaticProps, return về 1 object props là { repo }, ở component  Page mình nhập props  repo, đoạn này giống React bình thường thôi và mình dùng  repo để xử lý (sử dụng) data và render nó thông qua component con là  <HomePage />.

Để tìm hiểu thêm về cách hoạt động của  getStaticProps, hãy xem bài viết tính năng cache data của Next.js

Đường dẫn trang của bạn phụ thuộc vào dữ liệu bên ngoài

– Một trường hợp nữa là khi có 1 danh sách các sản phẩm, chúng ta sẽ cần vào xem chi tiết sản phẩm đó, thường thì chúng ta sẽ dùng id của sản phẩm để lấy thông tin chi tiết. Và id đó được gọi là Dynamic Parameters.

– Chúng ta tạo file  pages/product/[id].tsx ở đây chúng ta sẽ có  id là params id của mỗi product, đây là Dynamic Parameters, đoạn code trên ở getStaticProps thêm 1 params là context, và từ đó ta có thể lấy được id để fetch được data của product với id ở đường dẫn. Cùng xem đoạn code dưới dây để hiểu hơn về cách lấy data với Dynamic Parameters:

– Chúng ta thử chạy đoạn code ở trên nhé! Opps lỗi rồi 😃

– Giờ Next.js yêu cầu chúng ta thêm getStaticPaths ở đây, nếu chúng ta muốn dùng Dynamic Parameters với getStaticProps, bạn cần định nghĩa trước các đường dẫn được tạo, ví dụ mình lấy ra một list các product, mình muốn lấy data chi tiết cho từng product theo id, mình sẽ cần khai báo trước list id post đó ở trong getStaticPaths ví dụ:

– Với ví dụ bên trên thì Next.js đã định nghĩa cho chúng ta các đường dẫn với id = 1id = 2 . Tuy nhiên, các chúng ta cần là dữ liệu động, có bao nhiêu product thì phần paths kia sẽ có từng đó id. Giờ mình sẽ sửa lại file đầy đủ như sau:

– Và bây giờ chúng ta đã có thể xem trang chi tiết sản phẩm rồi.

– Ở đoạn code trên bạn sẽ thấy phần reutrn ở getStaticPaths có  fallback , vậy fallback là gì? chúng ta sẽ cùng tìm hiểu về fallback trong getStaticPaths luôn nhé:

getStaticPathsfallback :

fallback  có 3 giá trị ( false, true, ‘blocking’). Tìm hiểu chi tiết hơn tại https://nextjs.org/docs/pages/api-reference/functions/get-static-paths#fallback-blocking

Một số lưu ý về getStaticProps

  • getStaticProps chỉ chạy ở server-side.
  • Có thể code server side trực tiếp trong getStaticProps .
  • Có thể truy cập file system hoặc query database trong getStaticProps .
  • Không cần lo lắng về việc lộ API trong getStaticProps vì nó sẽ không được gửi về browser.
  • getStaticProps chỉ được chạy trong pages mà không phải ở component thường.
  • getStaticProps phải trả về một object và object phải chứa props key là một object.
  • getStaticProps sẽ chạy tạo build time. Nhưng khi develop ở local, getStaticProps chạy mỗi lần request.

Một số lưu ý về getStaticPaths

  • Nên sử dụng  getStaticPaths nếu bạn đang pre-render các trang tĩnh và sử dụng dynamic routes và data được trả về từ database,..
  •  getStaticPaths phải được sử dụng với  getStaticProps .
  • Không thể sử dụng  getStaticPaths với  getServerSideProps .
  • Không thể export  getStaticPaths từ tệp non-page (components folder).

3. Server-side Rendering (SSR)

– Để sử dụng Server-side Rendering cho một trang, bạn cần export một  async function có tên là  getServerSideProps. Function này sẽ được máy chủ gọi theo mọi yêu cầu.

– Giả sử trang của bạn cần hiển thị trước dữ liệu được cập nhật thường xuyên (được fetch từ API). Bạn có thể viết  getServerSideProps để fetch data và chuyển nó đến page như bên dưới:

– Như bạn có thể thấy, getServerSideProps tương tự như getStaticProps, nhưng điểm khác biệt là getServerSideProps được chạy theo mọi yêu cầu thay vì theo thời gian sử dụng.

– Tôi sẽ sửa đổi  pages/index.tsx về dạng getServerSideProps như sau: