Don't miss Vue.js Amsterdam in March 2025! Save 10% with code NUXT.
Релиз·  

Введение в Nuxt Scripts

Nuxt Scripts обеспечивает лучшую производительность, конфиденциальность, безопасность и удобство разработчика для сторонних скриптов.

Команда Nuxt в сотрудничестве с командой Chrome Aurora в Google с радостью объявляет о выпуске публичной бета-версии Nuxt Scripts.

Nuxt Scripts — это лучший способ работы с сторонними скриптами, обеспечивающий улучшенную производительность, конфиденциальность, безопасность и удобство разработчика.

Nuxt Scripts баннер

Путь к Nuxt Scripts

Более года назад Дэниел опубликовал первоначальный Nuxt Scripts RFC. В RFC было предложено создать модуль, который позволит "управлять и оптимизировать сторонние скрипты, следуя лучшим практикам для производительных и соответствующих стандартам веб-сайтов".

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

Используя RFC как семя идеи, я начал прототипировать, как это может выглядеть используя Unhead.

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

Зачем создавать модуль для сторонних скриптов?

94% сайтов используют хотя бы одного стороннего провайдера, при этом средний сайт имеет пять сторонних провайдеров.

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

Однако они фундаментально полезны и не собираются исчезать в ближайшее время.

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

😒 Удобство разработчика: головная боль полного цикла

Давайте рассмотрим процесс добавления стороннего скрипта в ваше приложение Nuxt с использованием вымышленного скрипта tracker.js, который добавляет функцию track в объект window.

Мы начнем с загрузки скрипта с помощью useHead.

useHead({ scripts: [{ src: '/tracker.js', defer: true }] })

Однако теперь давайте попробуем заставить функциональность скрипта работать в нашем приложении.

Следующие шаги являются общими при работе со сторонними скриптами в Nuxt:

  • Все должно быть обернуто для безопасности SSR.
  • Ненадежные проверки, загружен ли скрипт.
  • Расширение объекта window для типов.
<script setup>
// ❌ Упс, объект window не определен!
// 💡 Объект window не может быть напрямую доступен, если мы используем SSR в Nuxt.
// 👉 Нам нужно сделать это безопасным для SSR
window.track('page_view', useRoute().path)
</script>

🐌 Производительность: "Почему я не могу получить 100 баллов в Lighthouse?"

Для того чтобы посетитель мог начать взаимодействовать с вашим сайтом на Nuxt, необходимо загрузить пакет приложения, и Vue должен гидрировать экземпляр приложения.

Загрузка сторонних скриптов может мешать этому процессу гидратации, даже если используются async или defer. Это замедляет работу сети и блокирует основной поток, что приводит к ухудшению пользовательского опыта и плохим Core Web Vitals.

Отчет о пользовательском опыте Chrome показывает, что сайты на Nuxt с многочисленными сторонними ресурсами обычно имеют более низкие показатели Interaction to Next Paint (INP) и Largest Contentful Paint (LCP).

Чтобы увидеть, как сторонние скрипты ухудшают производительность, мы можем обратиться к Web Almanac 2022. В отчете показано, что 10 лучших сторонних скриптов в среднем имеют медианное время блокировки 1,4 секунды.

🛡️ Конфиденциальность и безопасность: не творите зла?

Из 10 000 лучших сайтов 58% из них имеют сторонние скрипты, которые обмениваются идентификаторами отслеживания, хранящимися во внешних куках, что означает, что они могут отслеживать пользователей на разных сайтах, даже если сторонние куки отключены.

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

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

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

Что делает Nuxt Scripts с этими проблемами?

Композабл: useScript

Этот композабл находится между тегом <script> и функциональностью, добавленной в window.{thirdPartyKey}.

Для тега <script>, композабл:

  • Предоставляет полную видимость состояний загрузки и ошибок скрипта
  • Загружает скрипты по умолчанию, пока Nuxt гидрирует приложение, для небольшого улучшения производительности.
  • Ограничивает crossorigin и referrerpolicy для улучшения конфиденциальности и безопасности.
  • Предоставляет способ отложить загрузку скрипта до тех пор, пока он вам не понадобится.

Для API скриптов он:

  • Обеспечивает полную безопасность типов вокруг функций скрипта
  • Добавляет прокси-слой, позволяющий вашему приложению работать, когда функции скрипта находятся в небезопасных контекстах (SSR, до загрузки скрипта, скрипт заблокирован)
const { proxy, onLoaded } = useScript('/hello.js', {
  trigger: 'onNuxtReady',
  use() {
    return window.helloWorld
  }
})

onLoaded(({ greeting }) => {
  // ✅ Скрипт загружен! Подключается к жизненному циклу Vue
})

// ✅ ИЛИ используйте прокси API - дружественный к SSR, вызывается при загрузке скрипта
proxy.greeting() // Привет, Мир!

declare global {
  interface Window {
    helloWorld: {
      greeting: () => 'Привет, Мир!'
    }
  }
}

Реестр скриптов

Реестр скриптов это коллекция первоочередных интеграций для распространенных сторонних скриптов. На момент выпуска мы поддерживаем 21 скрипт, с большим количеством в планах.

Реестр Nuxt Scripts

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

Например, мы можем рассмотреть скрипт Fathom Analytics.

const { proxy } = useScriptFathomAnalytics({
  // ✅ параметры проверяются во время выполнения
  site: undefined
})
// ✅ типизированный
proxy.trackPageview()

Фасадные компоненты

Реестр включает несколько фасадных компонентов, таких как Google Maps, YouTube и Intercom.

Фасадные компоненты — это "фальшивые" компоненты, которые гидрируются при загрузке стороннего скрипта. Фасадные компоненты имеют компромиссы, но могут значительно улучшить производительность. Подробнее см. в руководстве Что такое фасадные компоненты? для получения дополнительной информации.

Nuxt Scripts предоставляет фасадные компоненты как доступные, но безголовые, что означает, что они не стилизованы по умолчанию, но добавляют необходимые данные a16y.

Click to load

Clicking the video will load the YouTube iframe and start the video.

Управление согласием и триггеры событий элементов

Композабл useScript дает вам полный контроль над тем, как и когда ваши скрипты загружаются, либо предоставляя пользовательский trigger, либо вручную вызывая функцию load().

На основе этого Nuxt Scripts предоставляет расширенные триггеры, чтобы сделать это еще проще.

  • Управление согласием - Загружать скрипты только после того, как пользователь дал согласие, например, с помощью баннера о куках.
  • Триггеры событий элементов - Загружать скрипты на основе взаимодействий пользователя, таких как прокрутка, клик или отправка формы.
const cookieConsentTrigger = useScriptTriggerConsent()
const { proxy } = useScript<{ greeting: () => void }>('/hello.js', {
  // скрипт будет загружен только после того, как согласие будет принято
  trigger: cookieConsentTrigger
})
// ...
function acceptCookies() {
  cookieConsentTrigger.accept()
}
// greeting() ставится в очередь до тех пор, пока пользователь не примет куки
proxy.greeting()

Объединение скриптов

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

  • Конфиденциальность: Сторонний скрипт может отслеживать пользователей на разных сайтах.
  • Безопасность: Сторонний скрипт может быть скомпрометирован и внедрить вредоносный код.
  • Производительность: Дополнительные DNS-запросы замедлят загрузку страницы.
  • Удобство разработчика: Согласованные скрипты могут быть заблокированы блокировщиками рекламы.

Чтобы смягчить это, Nuxt Scripts предоставляет способ объединить сторонние скрипты в ваш публичный каталог без какой-либо дополнительной работы.

useScript('https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js', {
  bundle: true,
})

Скрипт теперь будет обслуживаться с вашего собственного домена по адресу /_scripts/{hash}.

Продолжение следует

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

Первоначальный релиз Nuxt Scripts решил некоторые из этих проблем, но перед нами все еще много работы.

Следующие пункты на дорожной карте:

Мы будем рады вашему вкладу и поддержке.

Начало работы

Чтобы начать работу с Nuxt Scripts, мы создали учебник, чтобы помочь вам быстро начать.

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

И большое спасибо ранним участникам.

Участники Nuxt Scripts

← Вернуться к блогу