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

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

Лина Сохони
Leena Sohoni
Хуссейн Джирдех
Houssein Djirdeh

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

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

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

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

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

Аудиты 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

Компонент 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, как их приложение использует скрипт, указав стратегию. Это позволяет фреймворку применять оптимизации и лучшие практики для загрузки скрипта, обеспечивая при этом наилучшую последовательность загрузки.

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

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

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

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

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

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

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

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

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

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

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

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

Что дальше для компонента Script?

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

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

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

С текущей реализацией компонента скрипта 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. Основываясь на отзывах, мы также надеемся улучшить компонент Script , чтобы охватить дополнительные варианты использования.

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

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