Пакет Next.js для управления сторонними библиотеками.

В 2021 году команда Chrome Aurora представила компонент Script для повышения производительности загрузки сторонних скриптов в Next.js. С момента его запуска мы расширили его возможности, чтобы упростить и ускорить загрузку сторонних ресурсов для разработчиков.

В этом сообщении блога представлен обзор новых функций, которые мы выпустили, в первую очередь библиотеки @next/третьих сторон , а также обзор будущих инициатив в нашей дорожной карте.

Влияние сторонних скриптов на производительность

41% всех сторонних запросов на сайтах Next.js — это скрипты. В отличие от других типов контента, загрузка и выполнение сценариев может занять значительное время, что может блокировать рендеринг и задерживать интерактивность пользователя. Данные из отчета об опыте пользователей Chrome (CrUX) показывают, что сайты Next.js, загружающие больше сторонних скриптов, имеют более низкие показатели взаимодействия с Next Paint (INP) и наибольшего контента с отрисовкой (LCP) .

Гистограмма, показывающая снижение процента Next.js, получившего хорошие оценки INP и LCP, пропорционально количеству загруженных сторонних разработчиков.
Отчет CruUX за декабрь 2023 г. (110 823 сайта)

Корреляция, наблюдаемая на этой диаграмме, не подразумевает причинно-следственной связи. Однако локальные эксперименты предоставляют дополнительные доказательства того, что сторонние скрипты существенно влияют на производительность страницы. Например, на диаграмме ниже сравниваются различные лабораторные показатели, когда контейнер Диспетчера тегов Google, содержащий 18 случайно выбранных тегов, добавляется в Taxonomy , популярный пример приложения Next.js.

Гистограмма, показывающая разницу в различных лабораторных показателях при загрузке сайта с помощью Диспетчера тегов Google и без него.
WebPageTest (мобильная связь 4G – Вирджиния, США)

Документация WebPageTest содержит подробную информацию о том, как измеряются эти тайминги. С первого взгляда становится ясно, что на все эти лабораторные показатели влияет контейнер GTM. Например, общее время блокировки (TBT) — полезный лабораторный показатель, приближающийся к INP — увеличилось почти в 20 раз.

Компонент сценария

Когда мы включили компонент <Script> в Next.js, мы позаботились о том, чтобы представить его через удобный API, который очень похож на традиционный элемент <script> . Используя его, разработчики могут разместить сторонний скрипт в любом компоненте своего приложения, а Next.js позаботится об упорядочивании сценария после загрузки критически важных ресурсов.

<!-- By default, script will load after page becomes interactive -->
<Script src="https://example.com/sample.js" />

<!-- Script is injected server-side and fetched before any page hydration occurs -->
<Script strategy=”beforeInteractive” src="https://example.com/sample.js" />

<!-- Script is fetched later during browser idle time -->
<Script strategy=”lazyOnload” src="https://example.com/sample.js" />

Десятки тысяч приложений Next.js, включая такие популярные сайты, как Patreon , Target и Notion , используют компонент <Script> . Несмотря на его эффективность, некоторые разработчики выразили обеспокоенность по поводу следующих вещей:

  • Где разместить компонент <Script> в приложении Next.js, следуя различным инструкциям по установке различных сторонних поставщиков (опыт разработчика) .
  • Какую стратегию загрузки оптимальнее использовать для разных сторонних скриптов (пользовательский опыт) .

Чтобы решить обе эти проблемы, мы запустили @next/third-parties — специализированную библиотеку, предлагающую набор оптимизированных компонентов и утилит, адаптированных для популярных сторонних разработчиков.

Опыт разработчиков: упрощение управления сторонними библиотеками

Многие сторонние скрипты используются на значительном проценте сайтов Next.js, причем наиболее популярным является Google Tag Manager, который используется на 66% сайтов соответственно . @next/third-parties строится на основе компонента <Script> путем введения оболочек более высокого уровня, предназначенных для упрощения использования в этих распространенных случаях.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleTagManager gtmId="GTM-XYZ" />
    </html>
  );
}

Google Analytics — еще один широко используемый сторонний скрипт ( 52% сайтов Next.js ) — также имеет собственный выделенный компонент.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleAnalytics gaId="G-XYZ" />
    </html>
  );
}

@next/third-parties упрощает процесс загрузки часто используемых скриптов, но также расширяет наши возможности по разработке утилит для других сторонних категорий, таких как встраивание. Например, вставки Google Maps и YouTube используются на 8% и 4% веб-сайтов Next.js соответственно, и мы также предоставили компоненты, упрощающие их загрузку.

import { GoogleMapsEmbed } from "@next/third-parties/google";
import { YouTubeEmbed } from "@next/third-parties/google";

export default function Page() {
  return (
    <>
      <GoogleMapsEmbed
        apiKey="XYZ"
        height={200}
        width="100%"
        mode="place"
        q="Brooklyn+Bridge,New+York,NY"
      />
      <YouTubeEmbed videoid="ogfYd705cRs" height={400} params="controls=0" />
    </>
  );
}

Пользовательский опыт: ускорение загрузки сторонних библиотек

В идеальном мире каждая широко распространенная сторонняя библиотека была бы полностью оптимизирована, что сделало бы ненужными любые абстракции, улучшающие ее производительность. Однако до тех пор, пока это не станет реальностью, мы можем попытаться улучшить их пользовательский опыт за счет интеграции через популярные фреймворки, такие как Next.js. Мы можем экспериментировать с различными методами загрузки, обеспечивать правильную последовательность сценариев и, в конечном итоге, делиться своими отзывами со сторонними поставщиками, чтобы стимулировать внесение изменений в исходную версию.

Возьмем, к примеру, встраивание YouTube. Где некоторые альтернативные реализации имеют гораздо лучшую производительность, чем встроенная версия. В настоящее время компонент <YouTubeEmbed> , экспортируемый @next/third-parties использует lite-youtube-embed , который, как показано в сравнении Next.js «Hello, World», загружается значительно быстрее.

GIF-изображение, показывающее сравнение загрузки страницы между компонентом YouTube Embed и обычным iframe YouTube.
WebPageTest (мобильная связь 4G – Вирджиния, США)

Аналогичным образом, для Карт Google мы включаем loading="lazy" в качестве атрибута по умолчанию для встраивания, чтобы гарантировать, что карта загружается только тогда, когда она находится на определенном расстоянии от области просмотра. Это может показаться очевидным атрибутом, который необходимо включить — тем более, что документация Google Maps включает его в пример фрагмента кода — но только 45% сайтов Next.js , встраивающих Google Maps, используют loading="lazy" .

Запуск сторонних скриптов в веб-воркере

Один из продвинутых методов, которые мы изучаем в @next/third-parties — это упрощение выгрузки сторонних скриптов веб-работнику. Популяризированный такими библиотеками, как Partytown , он может существенно снизить влияние сторонних скриптов на производительность страницы, полностью переместив их из основного потока.

Следующий анимированный GIF-файл показывает изменения в длительных задачах и времени блокировки основного потока при применении различных стратегий <Script> к контейнеру GTM на сайте Next.js. Обратите внимание: хотя переключение между вариантами стратегии лишь задерживает время выполнения этих сценариев, перемещение их в веб-воркер полностью сокращает их время в основном потоке.

GIF-изображение, показывающее различия во времени блокировки основного потока для разных стратегий сценария.
WebPageTest (мобильная связь 4G – Вирджиния, США)

В этом конкретном примере перенос выполнения контейнера GTM и связанных с ним скриптов тегов на веб-воркер снизил TBT на 92% .

Стоит отметить, что при неосторожном использовании этот метод может незаметно сломать многие сторонние скрипты, что усложнит отладку. В ближайшие месяцы мы проверим, правильно ли работают какие-либо сторонние компоненты, предлагаемые @next/third-parties при запуске в веб-воркере. Если да, то мы будем работать над тем, чтобы предоставить разработчикам простой и необязательный способ использования этой техники.

Следующие шаги

В процессе разработки этого пакета стало очевидно, что существует необходимость централизовать рекомендации по загрузке сторонних разработчиков, чтобы другие платформы также могли извлечь выгоду из тех же базовых методов. Это побудило нас создать Third Party Capital — библиотеку, использующую JSON для описания сторонних методов загрузки, которая в настоящее время служит основой для @next/third-parties .

В качестве наших следующих шагов мы продолжим концентрироваться на улучшении компонентов, предоставляемых для Next.js, а также расширим наши усилия по включению аналогичных утилит в другие популярные фреймворки и платформы CMS. В настоящее время мы сотрудничаем с сопровождающими Nuxt и планируем в ближайшем будущем выпустить аналогичные сторонние утилиты, адаптированные к их экосистеме.

Если один из сторонних разработчиков, которые вы используете в своем приложении Next.js, поддерживается @next/third-parties , установите пакет и попробуйте! Мы будем рады услышать ваши отзывы на GitHub .