Why should you read this blog?
- As the title said: “Boost NextJS TTI & FID performance without compromise and pain”
- Islands Architectures for Nextjs
Result
Before
https://next-lazy-hydrate-origin.vercel.app/
After
https://next-lazy-hydrate-optimized.vercel.app/
Hydrating is PURE OVERHEAD
As described in the post above, Hydration
progress is PURE OVERHEAD since you need to load the code and render the component twice.
Imagine you have a very long landing page built by Nextjs and most of it is a static component, then when you hit the Enter in the URL:
- HTML contains all your landing page content sent to the browser (Which is the result of SSR)
- JavaScript is downloaded to the browser, get parsed, and executed (Most of it contains text content only which is nearly the same as your HTML)
- Which Javascript downloaded, now it attaches events to the DOM. Now your website is fully usable
The second moves make most of SSR page has TTI (Time To Interactive) and FID (First Input Delay) so high
Progressive Hydration
Let’s take a step to optimize our long-landing-page. Because on our landing page, most of the component is static (Only text and image, nothing much called “interactive”) so it’s a waste of time to hydrate those components. What if we disable hydrate for some components or only hydrate components when it’s in the Viewport
This can easily archive using react-hydration-on-demand
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" },
}}
/>
);
}
}
Now you can optimize the 3rd bullet - Reduce the time JavaScript executed to hydrate our landing page. Good job!
Lazy load component code and hydrate when needed
We can save some executed time using react-hydration-on-demand
but we still have lots of redundancy code here.
JavaScript of those components is still downloaded and parsed, it just doesn’t get executed.
Do we have any way to fully render the HTML of the website but only load the component’s JS only when needed?
There is an answer for that: https://www.patterns.dev/posts/islands-architecture/
The idea is quite simple:
- Fully render HTML in SSR
- Load a really minimum of JavaScript to listen to the events
- If an event is fired, load the JS related to it and executed
This solution comes with a huge performance boost by scarifying a little time between every user’s interactive. But I do think it worse doing so 🌟
Disable Javascript reduces the TTI more than 7 times. What if we can remove half of it?
This is nice! The solution is simple but quite hard to do. Why?
- Because Reactjs only supports hydrating a full application (It will be solved when v18 is fully implemented). The
react-hydration-on-demand
actually do some trick to skip the hydrating process - In Nextjs, if the component is defined as
dynamic
and it renders in SSR, its JS also gets sent to the browser right away so nothing calledlazy
here
Read more
Why Progressive Hydration is Harder than You Think
So I make a package that can
- Skip the component hydrating process. Heavily based on
react-hydration-on-demand
- Remove the JS from the bundle and make you control when the JS is loaded
How can I do this trick? Check it out
Here is the result
How to use it
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
The API is quite simple, I’d love to see how this package can help you Boost NextJS TTI & FID performance without compromise and pain
Original post: https://thanhle.blog/en/blog/boost-nextjs-tti-fid-performance-without-compromise-and-pain
Top comments (0)