Почему вы должны читать этот блог?

  • Как сказано в заголовке: «Увеличьте производительность NextJS TTI и FID без компромиссов и боли».
  • Архитектура островов для Nextjs

Результат

До

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

Живая проверка PageSpeed

После

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

Живая проверка PageSpeed

Увлажнение — это ЧИСТОЕ НАЛОЖНОЕ УВЛАЖНЕНИЕ

https://www.builder.io/blog/hydration-is-pure-overhead

Как описано в посте выше, Hydration прогресс - это ЧИСТЫЕ НАЛОЖНЫЕ НАЛОЖЕНИЯ, поскольку вам нужно дважды загрузить код и отрисовать компонент.

Представьте, что у вас есть очень длинная целевая страница, созданная Nextjs, и большая ее часть представляет собой статический компонент, а затем, когда вы нажмете Enter в URL-адресе:

  1. HTML содержит все содержимое вашей целевой страницы, отправленное в браузер (что является результатом SSR).
  2. JavaScript загружается в браузер, анализируется и выполняется (большая его часть содержит только текстовый контент, который почти такой же, как ваш HTML)
  3. Какой 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 без компромиссов и боли.