Оптимизация загрузки сторонних скриптов в Next.js

Поймите концепцию компонента Next.js Script, который предоставляет встроенное решение для оптимизации загрузки сторонних скриптов.

Около 45% запросов с веб-сайтов, обслуживаемых на мобильных устройствах и компьютерах, являются сторонними запросами, из которых 33% — скриптами . Размер, задержка и загрузка сторонних скриптов могут существенно повлиять на производительность сайта. Компонент Next.js Script включает в себя встроенные лучшие практики и настройки по умолчанию, которые помогают разработчикам внедрять сторонние сценарии в свои приложения, одновременно устраняя потенциальные проблемы с производительностью «из коробки».

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

Сторонние сценарии позволяют веб-разработчикам использовать существующие решения для реализации общих функций и сокращения времени разработки. Но у создателей этих скриптов обычно нет стимула учитывать влияние на производительность веб-сайта-потребителя. Эти сценарии также являются «черным ящиком» для разработчиков, которые их используют.

Скрипты составляют значительное количество сторонних байтов , загружаемых веб-сайтами по различным категориям сторонних запросов. По умолчанию браузер отдает приоритет сценариям в зависимости от того, где они находятся в документе, что может задержать обнаружение или выполнение сценариев, важных для взаимодействия с пользователем.

Сторонние библиотеки, необходимые для макета, следует загружать заранее, чтобы отобразить страницу. Сторонние программы, которые не требуются для первоначального рендеринга, должны быть отложены, чтобы они не блокировали другую обработку в основном потоке. Lighthouse имеет два аудита для выявления сценариев блокировки рендеринга или блокировки основного потока.

Маяковые аудиты для устранения ресурсов, блокирующих рендеринг, и минимизации использования сторонних ресурсов.

Важно учитывать последовательность загрузки ресурсов вашей страницы, чтобы критические ресурсы не задерживались, а некритические ресурсы не блокировали критические ресурсы.

Несмотря на то, что существуют передовые методы снижения влияния третьих сторон, не все могут знать, как их реализовать для каждой третьей стороны, которую они используют. Это может быть сложно, потому что:

  • В среднем веб-сайты используют от 21 до 23 различных третьих лиц , включая скрипты, на мобильных устройствах и компьютерах. Использование и рекомендации могут отличаться для каждого.
  • Реализация многих сторонних разработчиков может различаться в зависимости от того, используется ли конкретная платформа или библиотека пользовательского интерфейса.
  • Часто появляются новые сторонние библиотеки.
  • Различные бизнес-требования, относящиеся к одной и той же третьей стороне, затрудняют разработчикам стандартизацию ее использования.

Акцент Aurora на сторонних скриптах

Часть сотрудничества Aurora с веб-фреймворками и инструментами с открытым исходным кодом заключается в предоставлении надежных настроек по умолчанию и специализированных инструментов, которые помогут разработчикам улучшить аспекты пользовательского опыта, такие как производительность, доступность, безопасность и готовность к мобильным устройствам. В 2021 году мы сосредоточились на том, чтобы помочь стекам фреймворков улучшить взаимодействие с пользователем и показатели Core Web Vitals .

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

Чтобы решить проблему блокировки основного потока сторонних скриптов, используемых в приложении, мы создали компонент Script . Компонент инкапсулирует функции секвенирования, чтобы предоставить разработчикам лучший контроль над загрузкой сторонних скриптов.

Упорядочение сторонних скриптов без компонента платформы

Доступное руководство по снижению влияния сценариев блокировки рендеринга предоставляет следующие методы для эффективной загрузки и упорядочения сторонних сценариев:

  1. Используйте атрибут async или defer с тегами <script> , которые сообщают браузеру загружать некритические сторонние скрипты, не блокируя анализатор документов. Скрипты, не необходимые для начальной загрузки страницы или первого взаимодействия с пользователем, могут считаться некритическими.

       <script src="https://example.com/script1.js" defer></script>
       <script src="https://example.com/script2.js" async></script>
    
  2. Установите ранние соединения с необходимыми источниками, используя preconnect и dns-prefetch. Это позволяет критическим сценариям начать загрузку раньше.

       <head>
           <link rel="preconnect" href="http://PreconnThis.com">
           <link rel="dns-prefetch" href="http://PrefetchThis.com">
       </head>
    
  3. Лениво загружайте сторонние ресурсы и встраивайте их после завершения загрузки содержимого основной страницы или когда пользователь прокручивает страницу вниз до той части страницы, где они включены.

Компонент Next.js Script

Компонент Next.js Script реализует описанные выше методы упорядочивания сценариев и предоставляет разработчикам шаблон для определения стратегии загрузки. Как только подходящая стратегия будет указана, она будет загружаться оптимально, не блокируя другие важные ресурсы.

Компонент Script основан на HTML-теге <script> и предоставляет возможность установить приоритет загрузки для сторонних сценариев с помощью атрибута Strategy.

// Example for beforeInteractive:
<Script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=IntersectionObserverEntry%2CIntersectionObserver" strategy="beforeInteractive" />

// Example for afterInteractive (default):
<Script src="https://example.com/samplescript.js" />

// Example for lazyonload:
<Script src="https://connect.facebook.net/en_US/sdk.js" strategy="lazyOnload" />

Атрибут стратегии может принимать три значения.

  1. beforeInteractive : этот параметр можно использовать для критических сценариев, которые должны выполняться до того, как страница станет интерактивной. Next.js гарантирует, что такие сценарии будут внедрены в исходный HTML на сервере и выполнены до другого встроенного JavaScript. Управление согласием, сценарии обнаружения ботов или вспомогательные библиотеки, необходимые для отображения критического контента, являются хорошими кандидатами для этой стратегии.

  2. afterInteractive : это применяемая по умолчанию стратегия, эквивалентная загрузке скрипта с атрибутом defer. Его следует использовать для сценариев, которые браузер может запускать после того, как страница станет интерактивной, например, для сценариев аналитики. Next.js внедряет эти сценарии на стороне клиента, и они запускаются после гидратации страницы. Таким образом, если не указано иное, все сторонние скрипты, определенные с помощью компонента Script, откладываются Next.js, тем самым обеспечивая строгий стандарт по умолчанию.

  3. lazyOnload : этот параметр можно использовать для отложенной загрузки сценариев с низким приоритетом, когда браузер бездействует. Функционал, предоставляемый такими скриптами, не требуется сразу после того, как страница становится интерактивной — например, плагины чата или социальных сетей.

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

Используя компонент «Сценарий», разработчики могут размещать сторонний сценарий в любом месте приложения для поздней загрузки сторонних приложений и на уровне документа для критически важных сценариев. Это означает, что компонент «Сценарий» может быть расположен рядом с компонентом, использующим сценарий. После гидратации скрипт будет внедрен в заголовок изначально визуализированного документа или в нижнюю часть тела, в зависимости от используемой стратегии.

Измерение воздействия

Мы использовали шаблоны коммерческого приложения Next.js и стартового блога для создания двух демонстрационных приложений, которые помогли оценить влияние включения сторонних скриптов. Часто используемые сторонние приложения для Google Tag Manager и встраивания в социальные сети сначала были включены на страницы этих приложений напрямую, а затем через компонент «Сценарий». Затем мы сравнили производительность этих страниц на WebPageTest .

Сторонние скрипты в коммерческом приложении Next.js

Сторонние скрипты были добавлены в шаблон коммерческого приложения для демонстрации, как показано ниже.

До После
Диспетчер тегов Google с асинхронным режимом Компонент скрипта со стратегией = afterInteractive для обоих скриптов
Кнопка Twitter Follow без асинхронности и отсрочки
Конфигурация сценария и компонента сценария для демонстрации 1 с двумя сценариями.

Следующее сравнение показывает визуальный прогресс для обеих версий стартового набора для коммерции Next.js. Как видно, LCP происходит почти на 1 секунду раньше, если компонент «Сценарий» включен и выбрана правильная стратегия загрузки.

Сравнение кинопленки, показывающее улучшение в LCP

Сторонние скрипты в блоге Next.js

Сторонние скрипты были добавлены в демонстрационное приложение блога, как показано ниже.

До После
Диспетчер тегов Google с асинхронным режимом Компонент сценария со стратегией = lazyonload для каждого из четырех сценариев.
Кнопка Twitter Follow с асинхронной функцией
Кнопка подписки на YouTube без асинхронности или отсрочки
Кнопка «Follow» в LinkedIn без асинхронности и отсрочки
Конфигурация сценария и компонента сценария для демонстрации 2 с 4 сценариями.
Видео, показывающее ход загрузки индексной страницы с компонентом «Скрипт» и без него. С компонентом Script происходит улучшение FCP на 0,5 секунды.

Как видно из видео, первая отрисовка контента (FCP) происходит за 0,9 секунды на странице без компонента «Скрипт» и за 0,4 секунды с компонентом «Скрипт».

Что будет дальше с компонентом Script

Хотя параметры стратегии afterInteractive и lazyOnload обеспечивают значительный контроль над сценариями блокировки рендеринга, мы также изучаем другие варианты, которые повысят полезность компонента Script.

Использование веб-воркеров

Веб-воркеры можно использовать для запуска независимых сценариев в фоновых потоках, что может освободить основной поток для обработки задач пользовательского интерфейса и повысить производительность. Веб-воркеры лучше всего подходят для выгрузки обработки JavaScript, а не работы пользовательского интерфейса, из основного потока. Сценарии, используемые для поддержки клиентов или маркетинга и обычно не взаимодействующие с пользовательским интерфейсом, могут быть хорошими кандидатами для выполнения в фоновом потоке. Облегченную стороннюю библиотеку — PartyTown — можно использовать для изоляции таких сценариев в веб-воркере.

При текущей реализации компонента сценария Next.js мы рекомендуем отложить выполнение этих сценариев в основном потоке, установив для стратегии значение afterInteractive или lazyOnload . В будущем мы предлагаем ввести новую опцию стратегии 'worker' , которая позволит Next.js использовать PartyTown или специальное решение для запуска сценариев на веб-воркерах. Мы приветствуем комментарии разработчиков по этому RFC .

Минимизация CLS

Сторонние встраивания, такие как реклама, видео или встраивание каналов социальных сетей, могут привести к смещению макета при отложенной загрузке. Это влияет на взаимодействие с пользователем и показатель совокупного смещения макета (CLS) страницы. CLS можно свести к минимуму, указав размер контейнера, в который будет загружаться встраивание.

Компонент Script можно использовать для загрузки встраивания, которое может привести к смещению макета. Мы рассматриваем возможность его расширения, чтобы предоставить параметры конфигурации, которые помогут уменьшить CLS. Это может быть доступно в самом компоненте Script или в качестве сопутствующего компонента.

Компоненты оболочки

Синтаксис и стратегия загрузки для включения популярных сторонних скриптов, таких как Google Analytics или Google Tag Manager (GTM), обычно фиксированы. Их можно дополнительно инкапсулировать в отдельные компоненты-оболочки для каждого типа сценария. Разработчикам будет доступен только минимальный набор атрибутов, специфичных для приложения (например, идентификатор отслеживания). Компоненты оболочки помогут разработчикам:

  1. Им будет проще включать популярные теги сценариев.
  2. Обеспечение того, чтобы фреймворк использовал наиболее оптимальную стратегию.

Заключение

Сторонние сценарии обычно создаются для включения определенных функций на веб-сайт-потребитель. Чтобы уменьшить влияние некритических сценариев, мы рекомендуем отложить их выполнение — что компонент Next.js Script делает по умолчанию. Разработчики могут быть уверены, что включенные сценарии не будут задерживать критические функции, если они явно не применят стратегию beforeInteractive . Как и компонент Next.js Script, разработчики фреймворков также могут рассмотреть возможность создания этих функций в других фреймворках. Мы активно изучаем возможность внедрения аналогичного компонента с командой Nuxt.js. Основываясь на отзывах, мы также надеемся улучшить компонент «Сценарий» , чтобы охватить дополнительные варианты использования.

Благодарности

Спасибо Каре Эриксон , Яникласу Ральфу , Кэти Хемпениус , Филиппу Уолтону , Джереми Вагнеру и Адди Османи за их отзывы об этом посте.