Review: Nextjs 13 - Kẻ dẫn đầu

Tại sao nên đọc bài này?

  • Tìm hiểu về framework mà mình đang/sẽ dùng
  • Pros/cons của Nextjs

Nextjs 13 có gì hot?

Demo, bạn có thể mở Dev Tool và mở tab Network xem mấy cái như Server Component, streaming, layout nó chạy như thế nào

Layout

notion image
 
Thằng layout này đẻ ra để giải quyết một số vấn đề:
  • Dev code layout khá mệt mỏi với approach trước đây, bạn phải tự tạo component layout rồi gắn các component con tương ứng theo url vào
  • Có nhiều app nextjs dùng để build Dashboard, mà nếu là dashboard thì thường sẽ có kiểu nested layout/componnet khá nhiều. Nếu có một approach để làm mấy cái này thì đỉnh
 
notion image
Nói một cách ngắn gọn: Nextjs support nested layout theo file structure để làm app có nested layout dễ dàng hơn.
Nó khá giống như việc trước đây Nextjs hỗ trợ route theo file structure, thay vì mình phải tự define trong file nào đó với support của react-route như trước đây.
Đọc thêm:
 

Uhm cũng hay, code có structure tốt thì dễ hiểu hơn. Nhưng có thứ còn hay hơn nữa

Component-level Data Fetching
Trước đây thì một thứ khiến Nextjs khác bọt là support một số cách fetch data ở Page level như getServerSideProps, getStaticProps thì bây giờ nếu dùng với Layout bên trên thì mình có thể làm chuyện đó với từng component
Ủa thì là fetch API ở component như trước giờ vẫn làm thôi mà?
À không, với concept Component-level Data Fetching thì nextjs support call API trên server và cả client cho từng component. Kết quả là server có thể trả về component với HTML code đã ready sẵn. Nó giống như page component được call api và render thành HTML rồi trả về cho client, nhưng cái này là ở level componnent
Tại sao call được API trên server và ở level component lại tốt hơn?
  • Query trực tiếp vào source data/database mà không lo bị leak key/account
  • Round trip ít hơn, ít phụ thuộc vào network của user hơn nếu query ở browser
  • Đưa nó gần tới level component thì sẽ giúp fetching data hiệu quả hơn. Cụ thể là cần thằng nào mới fetch thằng đó, thay vì trước đây phải fetch hết một lượt ở page level; hoặc là đẩy việc fetch xuống client, component nào fetch component đó
Màu xanh là API call, màu tím là JS bundle call
Màu xanh là API call, màu tím là JS bundle call
Parallel tách ra 2 phần rõ ràng, API phục vụ cho component, và JS bundle cho component đó.
Nói chung, để tận dụng được cái Parallel call này thì API của bạn sẽ nên hoàn toàn phụ thuộc vào URL, URL params chứ không được phụ thuộc vào state ở client
Đọc thêm:

Sờ tryming và súp pense (Streaming & Suspense)

Flow SSR trước đây
Flow SSR trước đây
Okey, flow SSR trước đây sẽ kiểu là:
  • Server call API
  • Server dùng API và code react, output ra HTML, gửi xuống browser
  • Browser download code về, render ra
SSR sẽ đợi tất cả component ready rồi mới send HTML code xuống cho browser
SSR sẽ đợi tất cả component ready rồi mới send HTML code xuống cho browser
Sờ tryming
notion image
Cơ bản thì thay vì đợi tất cả component render xong rồi mới gửi xuống browser thì chạy hết từ trên xuống dưới (Không cần đợi trong toàn app có component chưa render xong), lấy HTML rồi ném vào mặt browser
Kết quả sẽ như này:
Render lần đầu được trạng thái gì thì stream xuống browser luôn. Mấy thằng component sau này có kết quả thì stream thêm 1 lần nữa
Render lần đầu được trạng thái gì thì stream xuống browser luôn. Mấy thằng component sau này có kết quả thì stream thêm 1 lần nữa
Suspense là cơ chế để mình có thể tách các phần đó để có thể chạy async như trên hình. Với việc streaming thì sẽ support
  • TTFB, FCB, TTI nhỏ hơn
  • Mà nhỏ hơn thì user có thể thấy/tương tác với website nhanh hơn so với trước đây
Đọc thêm:
 

Server component

Hiểu đơn giản thì Server component chỉ run trên server và trả về HTML cho client thôi, không chạy được dưới client.
notion image
 
Server component có một vài lợi thế:
  • Nhiều khi mình cần rất nhiều code, thư viện chỉ để render ra HTML thôi. Nên nếu chỉ cho nó run ở server rồi trả về HTML cho browser thì mình không phải ship một đống node_module xuống cho client, tụi nó cũng không phải chạy lại logic để tới cuối có được HTML mong muốn
  • Trên server thì mình dễ control hơn. Máy user có thể “mạnh yếu mỗi đời khác nhau, song bug lúc nào cũng có! à nhầm nên performance cũng biến động nhiều”. Nếu tất cả đều chỉ nhận HTML từ server thì sự khác biết này sẽ không quá lớn
 
Đọc thêm:
 

Cơ bản là vậy, còn đây là mốt số điểm mình thấy chưa tốt hoặc là chưa khả thi

Minimum React 18

Cái này đối với mình gọi là “Ép người quá đáng”, React 18 có vẻ chưa ready để sử dụng vào thời điểm hiện tại. Vì sao?
Issue lớn nhất là React thêm cái vụ validateDOMNesting vào. Cái này làm gì? Nó sẽ validate cái DOM structure xem có đúng chuẩn HTML syntax không.
Kiểu như trong thẻ p thì không được có thẻ div ; trong table bắt buộc phải có tbody, không được skip qua
Nó không có gì sai cả, nhưng nó cực kì khó chịu. Code của bạn thì chịu khó sửa lại xíu cũng được, nhưng code trong thư viện thì cực kì suffer
Ví cái lỗi như trên mà trải nghiệm của mình là 90% không thể dụng React 18 cho SSR được, muốn dùng nextjs 13 thì bắt buộc phải đưa code về client hết. Vậy còn chậm hơn, thôi bố dùng Nextjs 12 cho rồi

Frontend giờ không còn chỉ là frontend nữa

Từ lúc bắt đầu code với Nextjs thì bạn cũng phải học thêm một số concept về data fetching, page file routing,… fix một số issue khi SSR.
Còn giờ thì bạn phải biết Server Component là gì kiểu gì, streaming run làm sao. Fetching data on server thì code thế nào, tổ chức làm sao,…
Bây giờ để làm được một app frontend ra gì và này nọ thì bạn phải biết cả server chạy như nào nữa.
Learning curve khi code Nextjs bắt đầu tăng lên rất nhiều. Mặc dù mình phải thừa nhận là kĩ năng của Dev bây giờ là phải adapt rất tốt, tuy nhiên cái gì càng ít phải spend thời gian học thì vẫn vui vẻ hơn nhỉ?
Có vẻ như vòng lặp lại bắt đầu. Trước đây là code backend xong làm thêm tí backend, sau này thì tách ra Frontend và Backend rõ ràng, giờ thì Frontend xong phải thêm tí backend cho nót chất’sss

Nó chỉ phù hợp với app dạng Dashboard

Thực ra cái Layout, Nested layout đồ với hầu hết app là không cần thiết lắm. Mình chỉ cần cái header/footer rồi gắn children vào là xong cho hầu hết các landing page.
Chỉ có tụi làm dashboard mới có nhu cầu nested sâu đến vậy, và với trải nghiệm lập trình của mình thì hầu hết dashboard tới 3 level là max à, sâu hơn thì rất hiếm và edge case.
Remix.run cũng là một framework tốt để build dashboard và cùng giải quyết vấn đề như trên. Đặc biệt nó còn không phải gặp rắc rối với React 18 nữa. Bài tuần sau mình sẽ viết về thằng này

Quá phụ thuộc vào Vercel

Serverless, edge function, streaming, server component, image optimizing,…
Toàn những thứ hay ho nhưng để run được thì bạn cần Vercel. Nếu không host trên vercel thì chạy không tốt, một số feature không support, hoặc là support thì cũng rất mệt mỏi để làm nó chạy được,…
Cái này về mặt biz thì mình hoàn toàn hiểu được, không build nextjs như vậy thì lấy user đâu mà bán Vercel 💁‍♂️
Nhưng về mặt dev hay devops thì chán bỏ mọe.
Do đó kì này cũng đang trend build thằng open-nextjs
 

Tổng kết

Nếu ai hỏi mình có nên dùng Nextjs 13 không? Mình sẽ trả lời là không, chưa phải thời điểm.
Ngoài ra nó có một số cái thì nghe hay đó, nhưng trên thực tế lại khá ít dùng. Do đó hãy cân nhắc bài toàn bạn muốn giải có phù hợp với Nextjs 13 không? Bài viết chỉ đưa ra góc nhìn của cá nhân mình, nếu bạn thấy nó vẫn phù hợp. Go Ahead!
 

Bài viết “lan quyên”

 

Loading Comments...

Follow me @thanhledev

Thứ 7 (24-12) lúc 9 giờ sáng mình có buổi workshop nhỏ chia sẻ cách viết Smart Contract dùng Solidity, target là chỉ cần biết code là làm được.
Nếu bạn hứng thú hãy tham gia nhé!