Почему вы должны читать этот блог?
- Как сказано в заголовке: «Увеличьте производительность NextJS TTI и FID без компромиссов и боли».
- Архитектура островов для Nextjs
Результат
До
https://next-lazy-hydrate-origin.vercel.app/
После
https://next-lazy-hydrate-optimized.vercel.app/
Увлажнение — это ЧИСТОЕ НАЛОЖНОЕ УВЛАЖНЕНИЕ
https://www.builder.io/blog/hydration-is-pure-overhead
Как описано в посте выше, Hydration
прогресс - это ЧИСТЫЕ НАЛОЖНЫЕ НАЛОЖЕНИЯ, поскольку вам нужно дважды загрузить код и отрисовать компонент.
Представьте, что у вас есть очень длинная целевая страница, созданная Nextjs, и большая ее часть представляет собой статический компонент, а затем, когда вы нажмете Enter в URL-адресе:
- HTML содержит все содержимое вашей целевой страницы, отправленное в браузер (что является результатом SSR).
- JavaScript загружается в браузер, анализируется и выполняется (большая его часть содержит только текстовый контент, который почти такой же, как ваш HTML)
- Какой Javascript скачал, теперь он привязывает события к DOM. Теперь ваш сайт полностью готов к использованию
Вторые шаги делают большую часть страницы SSR, имеют такие высокие TTI (время до взаимодействия) и FID (задержка первого ввода).
Прогрессивная гидратация
Давайте сделаем шаг, чтобы оптимизировать нашу длинную целевую страницу. Поскольку на нашей целевой странице большая часть компонентов статична (только текст и изображение, ничего особенного не называется «интерактивным»), поэтому гидратация этих компонентов — пустая трата времени. Что, если мы отключим гидратацию для некоторых компонентов или гидратируем только компоненты, когда они находятся в Viewport
Это можно легко заархивировать с помощью 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" }, }} /> ); } }
Теперь вы можете оптимизировать третий пункт — сократить время выполнения JavaScript для увлажнения нашей целевой страницы. Хорошая работа!
Отложенная загрузка кода компонента и гидратация при необходимости
Мы можем сэкономить некоторое время выполнения, используя react-hydration-on-demand
, но у нас все еще много избыточного кода.
JavaScript этих компонентов по-прежнему загружается и анализируется, он просто не выполняется.
Есть ли у нас способ полностью отобразить HTML веб-сайта, но загружать JS компонента только при необходимости?
На это есть ответ: https://www.patterns.dev/posts/islands-architecture/
Идея довольно проста:
- Полностью визуализировать HTML в SSR
- Загрузите действительно минимум JavaScript, чтобы слушать события
- Если событие запущено, загрузите связанный с ним JS и выполните
Это решение обеспечивает огромный прирост производительности за счет уменьшения времени между интерактивными действиями каждого пользователя. Но я думаю, что так будет хуже 🌟
Это мило! Решение простое, но довольно сложное. Почему?
- Потому что Reactjs поддерживает только гидратацию полного приложения (Это будет решено, когда v18 будет полностью реализована).
react-hydration-on-demand
на самом деле делают некоторые трюки, чтобы пропустить процесс увлажнения. - В Nextjs, если компонент определен как
dynamic
и он отображается в SSR, его JS также сразу же отправляется в браузер, поэтому здесь ничего не называетсяlazy
.
Читать далее
Почему прогрессивное увлажнение сложнее, чем вы думаете
Поэтому я делаю пакет, который может
- Пропустить процесс увлажнения компонентов. Сильно основано на
react-hydration-on-demand
- Удалите JS из пакета и заставьте вас контролировать, когда JS загружается.
Как я могу сделать этот трюк? Проверь это
Вот результат
https://user-images.githubusercontent.com/9281080/172079813-a49db8c0-c64d-4589-941d-bf027b22433a.mov
Как это использовать
Установить
npm install next-lazy-hydrate
yarn add next-lazy-hydrate
Использование
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> ); };
Документ
https://github.com/thanhlmm/next-lazy-hydra
API довольно прост, и мне бы очень хотелось узнать, как этот пакет поможет вам повысить производительность TTI и FID NextJS без компромиссов и боли.