- vừa được xem lúc

Optimize TTI và FID cho Nextjs một cách super đơn giản

0 0 26

Người đăng: Thanh Le

Theo Viblo Asia

Bài gốc: https://thanhle.blog/blog/optimize-tti-và-fid-cho-nextjs-mot-cach-super-don-gian

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

  • Như tít: “Optimize TTI và FID cho Nextjs một cách super đơn giản”
  • Islands Architectures cho Nextjs

Kết quả

Before

Untitled.png

https://next-lazy-hydrate-origin.vercel.app/

Live check PageSpeed

After

Untitled 1.png

https://next-lazy-hydrate-optimized.vercel.app/

Live check PageSpeed

Hydration là quá trình lãng phí tài nguyên

Server side rendering với Hydration lãng phí tài nguyên như thế nào?

Như bài viết trên, Hydration là quá trình khá LÃNG PHÍ TÀI NGUYÊN vì nó cần load code của component và render tới hai lần.

Tương tượng chúng ta có một trang landing page khá là dài viết bằng Nextjs, hầu hết các component đều là tĩnh (Nghĩa là chỉ render ra HTML mà không có quá nhiều Interactive). Khi chúng ta “đập” vào phím Enter trên thanh URL thì:

  1. Đống HTML của landing page được gửi xuống Browser (Là kết quả của quá trình SSR)
  2. JavaScript được download xuống Browser, phân tích, rồi thực thi (Đa số tụi nó sẽ bao gồm text và khá giống như HTML ở bước 1)
  3. Sau khi JavaScript được download, và chạy xong, nó sẽ gắn đống event cần handle vào cây DOM hiện tại. Bây giờ thì cái web của mình với có thể gọi là… load đầy đủ

Trong các bước trên, bước 2 và 3 khiến cho hai chỉ số TTI (Time To Interactive) và FID (First Input Delay) rất cao

Progressive Hydration

Xin không dịch từ trên quá tiếng Việt vì dịch ra sẽ rất chuối 🍌

Ok bây giờ thử optimize cái trang landing page dài ngoằng của chúng ta nhé. Bởi vì cái trang landing page đó hầu hết là Static Component nên hầu hết thời gian cho quá trình Hydrate Component là khá vô ích (bởi vì nó chỉ cần HTML, CSS là chạy được, méo cần JS nào ở đây cả). Vậy thì chỉ cần tắt hydrate cho những Component kiểu như vậy, hoặc là chỉ Hydrate khi nào có component nhảy vào màn hình (Viewport) của user.

Untitled 2.png

Cái này khá dễ để làm, cùng package react-hydration-on-demand là được

import withHydrationOnDemand from "react-hydration-on-demand";
import Card from "../Card"; // Hydrate when the component enters the viewport
const CardWithHydrationOnDemand = withHydrationOnDemand({ on: ["visible"] })( Card
); export default class App extends React.Component { render() { return ( <CardWithHydrationOnDemand title="my card" wrapperProps={{ className: "customClassName", style: { display: "contents" }, }} /> ); }
}

Vậy là bây giờ, cái gạch đầu dòng thứ 3 đã được optimize - giảm thời gian JS phải chạy để hydrate cái landing page yếu dấu của chúng ta 🥰

Lazy load component rồi hydrate khi cần thiết

Ở bước trên, ta có thể optimize executed time sử dụng react-hydration-on-demand nhưng nếu nhìn vào đống JS được gửi xuống bạn sẽ nhận ra

JS cho các component vẫn phải được download và parsed, nó chỉ đơn giản là không hoặc chưa execute thôi. 💡 Có cách nào mà mình vẫn render được full HTML nhưng chỉ load JS và Hydrate Component đó khi cần thiết không?

Trong quá trình tìm kiếm câu trả lời, thì đây là giải pháp mình thấy ưng ý nhất: https://www.patterns.dev/posts/islands-architecture/

Untitled 3.png

Ý tưởng thì khá đơn giản:

  • Render full trang ở quá trình SSR
  • Load tối thiểu JS, chỉ để listen trên cây DOM xem có event nào không
  • Nếu mà có event, thì load JS tương ứng rồi chạy nó thôi

Giải pháp này thực sự optimize performance rất rất nhiều, bằng cách hy sinh một chút thời gian mỗi khi user có interactive gì đó. Với mình cái trade-off này là cực kì “lời” 🌟

Nếu thử disable JS thì TTI giảm hơn 7 lần. Sẽ làm sao nếu chúng ta chỉ cần giảm một nửa trong số đó?

Nếu thử disable JS thì TTI giảm hơn 7 lần. Sẽ làm sao nếu chúng ta chỉ cần giảm một nửa trong số đó?

Đỉnh của chóp! Giải pháp khá dễ hiểu tuy nhiên ở thời điểm hiện tại thì khá khó để làm. Tại sao?

  • Ở thời điểm hiện tại, React chỉ support hydrate full một app chứ không phải riêng từng component (Nếu v18 được hoàn thiện thì sẽ giải quyết được cái này). Thực ra cái package react-hydration-on-demand nó có một số trick để bỏ qua quá trình Hydrate
  • Với Nextjs, nếu component được define là dynamic mà nếu nó được render ở quá trình SSR, thì đống JS của nó cũng được gửi xuống Browser ngay khi page load luôn, chả có gì gọi là lazy ở đây cả

Đọc thêm

Why Progressive Hydration is Harder than You Think

Vậy là mình quyết định viết một cái package có thể:

  • Bỏ qua quá trình Hydrate. Hầu hết là dựa theo thằng react-hydration-on-demand thôi 😃
  • Loại bỏ JS khi load page và khiến mình có thể tùy chỉnh khi nào thì load JS tương ứng

Làm sao mình làm được á hả? Xem thử ở đây nè (khá ngắn)

Còn đây là kết quả

https://user-images.githubusercontent.com/9281080/172079813-a49db8c0-c64d-4589-941d-bf027b22433a.mov

Cách dùng

Install

npm install next-lazy-hydrate
yarn add next-lazy-hydrate

Usage

import lazyHydrate from 'next-lazy-hydrate'; // Static component
const WhyUs = lazyHydrate(() => import('../components/whyus')); // Lazy hydrate when users hover the component
const Footer = lazyHydrate( () => import('../components/footer', { on: ['hover'] })
); const HomePage = () => { return ( <div> <AboveTheFoldComponent /> {/* ----The Fold---- */} <WhyUs /> <Footer /> </div> );
};

Document

https://github.com/thanhlmm/next-lazy-hydrate

API khi sử dụng package khá đơn giản, hy vọng nó giúp các đồng-coder khác Optimize TTI và FID cho Nextjs một cách super đơn giản

Nhớ Star ⭐ cho tui nha!

Bài gốc: https://thanhle.blog/blog/optimize-tti-và-fid-cho-nextjs-mot-cach-super-don-gian

Bình luận

Bài viết tương tự

- vừa được xem lúc

Một vài thủ thuật CSS mà chính Frontend có thể còn chưa biết (Phần 30)

. Hello xin chào mọi người, mình đã trở lại và tiếp tục với phần 30 của series về Một vài thủ thuật CSS mà chính Frontend có thể còn chưa biết. Bắt đầu thôi nào.

0 0 35

- vừa được xem lúc

5 câu hỏi phỏng vấn Frontend giúp bạn tự tin hơn khi sử dụng bất đồng bộ trong Javascript

Một trong những điều khó khăn khi học Javascript là promises. Chúng không dễ hiểu và có thể cần một vài hướng dẫn và một thời gian kha khá để vận dụng chúng.

0 0 81

- vừa được xem lúc

Một vài thủ thuật CSS mà chính Frontend có thể còn chưa biết (Phần 31)

Hello xin chào mọi người, mình đã trở lại và tiếp tục với phần 31 của series về Một vài thủ thuật CSS mà chính Frontend có thể còn chưa biết. Bắt đầu thôi nào.

0 0 33

- vừa được xem lúc

Những lý do khiến mình thích CSS custom properties hơn SASS variables?

Halo các bạn,. Lại là mình với một bài post liên quan tới chủ đề Front-end đây Mình còn nhớ hồi mình bắt đầu tìm hiểu và bị SASS lôi cuốn, mình đã nghĩ rằng mình sẽ chẳng bao giờ cần dùng đụng tới CSS

0 0 75

- vừa được xem lúc

Usability là gì? Những lưu ý khi thiết kế Usability

Usability là một yếu tố quan trọng trong sự thành bại của sản phẩm. Thật đáng tiếc khi sản phẩm làm ra ưu việt về tính năng, nhưng lại không được người dùng tiếp nhận, đơn giản chỉ vì khó sử dụng.

0 0 22

- vừa được xem lúc

7 Repos cho Front-End mà chính bạn còn không biết là bạn cần nó

. Những repos chẳng mấy khi được nhắc đến nhưng lại giúp bạn build mọi thứ nhanh hơn và tốt hơn nhiều. Chúng ta đang sống trong một thời đại có sẵn các công cụ và tài nguyên hoàn hảo, chúng chỉ cách t

0 0 26