логотип PurpleSchool
логотип PurpleSchool

Использование scripts в Nuxt

Автор

Олег Марков

Введение

Работая с Nuxt, вы, скорее всего, сталкивались с задачей подключения внешних или локальных скриптов — например, когда нужно подгрузить Google Analytics, какие-либо внешние библиотеки на JavaScript, либо встроить кастомный скрипт только на определённых страницах. Nuxt, как прогрессивный фреймворк для Vue.js, располагает собственными подходами к работе с подобными задачами и предоставляет разные возможности для управления scripts: от декларативного подключения во время сборки до динамического добавления скриптов в рантайме.

Давайте разберём все основные способы использования scripts в Nuxt, рассмотрим лучшие практики и посмотрим, как правильно интегрировать сторонние библиотеки — чтобы ваш проект был безопасным, устойчивым и быстрым.

Подключение scripts через nuxt.config

Один из самых удобных способов подключить внешний или локальный скрипт ко всем страницам вашего приложения — добавить нужные теги <script> через файл nuxt.config.

Использование head.scripts в Nuxt 2

В Nuxt 2 для добавления скриптов служит раздел head:

// nuxt.config.js
export default {
  head: {
    script: [
      // Пример подключения внешнего скрипта
      {
        src: 'https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXX-X',
        async: true // Асинхронная загрузка
      },
      // Локальный скрипт
      {
        src: '/js/custom.js',
        type: 'text/javascript'
      }
    ]
  }
}

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

Подключение через app.html

Иногда может быть удобно внести свои <script> прямо в шаблон app.html:

<!-- app.html -->
<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
  <head {{ HEAD_ATTRS }}>
    {{ HEAD }}
    <script src="/js/critical-scripts.js"></script>
  </head>
  <body {{ BODY_ATTRS }}>
    {{ APP }}
  </body>
</html>

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

Head scripts в Nuxt 3

В Nuxt 3 архитектура изменилась, теперь глобальные head-параметры настраиваются через app.vue или через собственное head API:

// app.vue (Nuxt 3)
<script setup>
useHead({
  script: [
    {
      src: 'https://cdn.jsdelivr.net/npm/frappe-charts@1.5.0/dist/frappe-charts.min.iife.js',
      defer: true
    }
  ]
})
</script>

Теперь, видите, управление скриптами стало проще — декларативно указываете нужные ресурсы прямо в компоненте. Вызывайте useHead в верхнем уровне проекта для «глобальных» скриптов, либо в конкретном компоненте/странице — для локальных.

Локальное и условное подключение scripts

В реальной жизни не все скрипты нужны на каждой странице. Например, платежные шлюзы нужны только на checkout, виджеты обратной связи — только в разделе поддержки, и т.д.

Скрипты только на определённой странице

Смотрите, как это можно сделать в Nuxt 3, добавив скрипт в конкретную страницу:

<!-- pages/checkout.vue -->
<script setup>
useHead({
  script: [
    {
      src: 'https://pay.example.com/widget.js',
      async: true
    }
  ]
})
</script>

В результате тег <script> появится только на этой странице. Это удобно для минимизации нагрузки и ускорения загрузки сайта.

Динамическое добавление скриптов в рантайме

Иногда нужно загрузить скрипт только тогда, когда это действительно требуется (например, после определённого пользовательского события). Стандартными средствами Nuxt вы этого не добьётесь — нужно использовать JavaScript.

Вот как это реализовать:

// utils/loadScript.js
export function loadScript(src) {
  return new Promise((resolve, reject) => {
    const script = document.createElement('script')
    script.src = src
    script.async = true
    script.onload = resolve
    script.onerror = reject
    document.head.appendChild(script)
  })
}

А теперь вызывайте этот метод в компоненте (только на клиенте!):

// Пример использования в компоненте (Nuxt 2/3)
import { loadScript } from '~/utils/loadScript'

onMounted(async () => {
  try {
    await loadScript('https://example.com/expensive-lib.js')
    // Теперь библиотека загружена, можно вызывать её API
  } catch (e) {
    // Если загрузка не удалась, обработайте ошибку
    console.error('Script load failed', e)
  }
})

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

Использование скриптов в Nuxt позволяет автоматизировать выполнение различных задач, таких как сборка проекта, запуск тестов и деплой на сервер. Умение работать со скриптами — это важный навык для любого Nuxt-разработчика, позволяющий повысить эффективность работы и упростить процесс разработки. Если вы хотите детальнее погрузиться в мир Nuxt, освоить все его тонкости и стать настоящим профессионалом — приходите на наш большой курс Nuxt - fullstack Vue фреймворк. На курсе 129 уроков и 13 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Интеграция внешних библиотек JavaScript

Nuxt оптимизирован под ES-модули, однако часто приходится подключать библиотеки, не поддерживающие import/export, либо доступные только как глобальные скрипты (например, Yandex.Metrika, чаты, рекламы и др.).

Инъекция глобальных библиотек

Подключив скрипт через head, как показано выше, вы получите доступ к глобальному объекту после загрузки страницы. Чтобы безопасно обращаться к API, проверьте, что объект уже доступен:

onMounted(() => {
  if (window.ym) {
    window.ym(123456, 'hit', '/some-page')
  }
})

Если вам необходима строгая последовательность (ожидать именно загрузку), стоит использовать промис-обёртку для loadScript, как показано выше.

Использование скриптов в Nuxt позволяет автоматизировать выполнение различных задач, таких как сборка проекта, запуск тестов и деплой на сервер. Умение работать со скриптами — это важный навык для любого Nuxt-разработчика, позволяющий повысить эффективность работы и упростить процесс разработки. Если вы хотите детальнее погрузиться в мир Nuxt, освоить все его тонкости и стать настоящим профессионалом — приходите на наш большой курс Nuxt - fullstack Vue фреймворк. На курсе 129 уроков и 13 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Использование Nuxt modules и plugins

Для популярных внешних скриптов зачастую существуют модули Nuxt, например, @nuxtjs/gtm для Google Tag Manager.

Установка:

npm install @nuxtjs/gtm

Конфиг:

// nuxt.config.js
export default {
  modules: [
    '@nuxtjs/gtm',
  ],
  gtm: {
    id: 'GTM-XXXXXXX'
  },
}

Плагинами удобно обрабатывать любые внешние библиотеки, если их нет среди официальных модулей. Создайте в каталоге plugins свой плагин:

// plugins/someLib.client.js
import { loadScript } from '~/utils/loadScript'

export default async () => {
  await loadScript('https://example.com/my.js')
  // Можно теперь использовать глобальную библиотеку
}

Добавьте его в nuxt.config.js:

export default {
  plugins: [
    '~/plugins/someLib.client.js'
  ]
}

Суффикс .client.js гарантирует запуск только на клиенте.

Безопасность, производительность и SEO

CSP и trusted-types

Иногда строгая политика Content Security Policy запрещает загрузку скриптов напрямую с внешних доменов либо inline-скриптов. Используя head.script, вы должны указать домены в вашей CSP, либо предпочесть загрузку через сервер.

Пример CSP для Google Analytics:

Content-Security-Policy: script-src 'self' https://www.googletagmanager.com

Ленивая загрузка (async, defer)

Предпочитайте использовать атрибуты async или defer. Они позволяют выполнять скрипты без блокировки основного потока загрузки страницы, что увеличивает скорость рендера.

  • async — выполняет скрипт сразу после загрузки, не дожидаясь построения DOM.
  • defer — выполняет скрипт после завершения построения DOM.

Пример:

{
  src: 'https://cdn.jsdelivr.net/npm/chart.js',
  defer: true
}

Inline скрипты

Иногда скрипт небольшой, и его имеет смысл инлайнить для ускорения. Например:

// nuxt.config.js
export default {
  head: {
    script: [
      {
        innerHTML: `
          window.initWidget = function() {
            // Контент скрипта
          }
        `,
        type: 'text/javascript',
        charset: 'utf-8'
      }
    ],
    __dangerouslyDisableSanitizersByTagID: {
      'inline-widget': ['innerHTML']
    }
  }
}

Обратите внимание: с инлайном скриптов будьте осторожны — это может влиять на CSP и потенциально ухудшать безопасность.

Практические рекомендации ("best practices")

Вот несколько советов, которые помогут вам эффективно работать с scripts в Nuxt:

  1. Минимизируйте количество сторонних скриптов. Каждый внешний скрипт увеличивает время загрузки страницы и может слабить защиту.
  2. Подключайте скрипты только там, где они нужны. Например, плагины оплаты — только на checkout.
  3. Используйте defer/async. Так вы ускоряете начальную загрузку страницы.
  4. Храните свои кастомные скрипты локально. Чтобы уменьшить зависимость от внешних сервисов.
  5. Следите за SEO-эффектами. Чрезмерное число скриптов или их неправильная загрузка ухудшают индексацию.
  6. Учитывайте работу с SSR. Скрипты, которым нужен access к window/document, подключайте только на клиенте (например, через плагин с .client.js).
  7. Используйте официальные Nuxt-модули для известных сервисов. Они более безопасны, поддерживают SSR и делегируют настройку многим best practices.

Типичные ошибки и их решение

Скрипты не работают на серверной стороне (SSR)

Если скрипт обращается к window или document, а вы используете SSR (что по умолчанию в Nuxt), обязательно размещайте скрипт только на клиентской стороне.

Пример плагина:

// plugins/widget.client.js
export default () => {
  window.someWidget.init()
}

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

Если вы динамически добавляете скрипты сами (например, через loadScript), всегда проверяйте, не добавлен ли скрипт уже в DOM:

// Проверка
if (!document.querySelector('script[src="https://cdn.example.com/lib.js"]')) {
  // Добавляем скрипт
}

Ошибки при доступе к глобальным функциям внешних библиотек

Убедитесь, что скрипт полностью загружен, прежде чем обращаться к его API. Используйте промисы или слушайте событие onload.

Примеры использования популярных внешних скриптов

Google Analytics (gtag.js) в Nuxt 2

export default {
  head: {
    script: [
      {
        src: 'https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXX-X',
        async: true
      },
      {
        innerHTML: `
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
          gtag('config', 'UA-XXXXXXX-X');
        `,
        type: 'text/javascript'
      }
    ],
    __dangerouslyDisableSanitizers: ['script']
  }
}

Facebook Pixel (Nuxt 3, отдельная страница)

<script setup>
useHead({
  script: [
    {
      innerHTML: `
        !function(f,b,e,v,n,t,s)
        {if(f.fbq)return;n=f.fbq=function(){n.callMethod?
        n.callMethod.apply(n,arguments):n.queue.push(arguments)};
        if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
        n.queue=[];t=b.createElement(e);t.async=!0;
        t.src=v;s=b.getElementsByTagName(e)[0];
        s.parentNode.insertBefore(t,s)}(window, document,'script',
        'https://connect.facebook.net/en_US/fbevents.js');
        fbq('init', 'XXXXXXXXXXXXXXX');
        fbq('track', 'PageView');
      `,
      type: 'text/javascript'
    }
  ]
})
</script>

Заключение

В Nuxt достаточно гибких возможностей для подключения и управления scripts, как на глобальном, так и на локальном уровне. Вы можете использовать как декларативные методы через API head, так и динамическое подключение в рантайме. Важно учитывать отличия между Nuxt 2 и Nuxt 3, соблюдать best practices по безопасности и производительности, а также следить за тем, чтобы скрипты не мешали работе SSR и не перегружали страницы.

Использование скриптов — это лишь один из аспектов разработки Nuxt-приложений. Чтобы стать настоящим профессионалом, необходимо освоить множество других навыков, таких как роутинг, работа с данными, стилизация и деплой. На курсе Nuxt - fullstack Vue фреймворк вы получите все необходимые знания и практические навыки для разработки современных веб-приложений на Nuxt. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир Nuxt прямо сегодня.

Частозадаваемые технические вопросы по теме статьи и ответы на них

Как гарантировать, что внешний скрипт загружается только на клиенте, а не на сервере (SSR)?

Создайте плагин с суффиксом .client.js в папке plugins и подключите его в nuxt.config. Такой плагин выполнится только на клиенте.

Как добавить inline script в Nuxt 3 и избежать его удаления санитайзером?

Используйте опцию useHead и добавьте атрибуту script поле children (для Vue 3), а чтобы избежать удаления, настройте __dangerouslyDisableSanitizers в nuxt.config или в useHead (для соответствующих ключей).

Можно ли подключать js-модули через import вместо head.script?

Если библиотека поддерживает ES-модули, всегда предпочтите import. Подключение через head.script оправдано только для глобальных, legacy и сторонних библиотек, не совместимых с import/export.

Почему Google Tag Manager не работает на некоторых страницах после динамического роутинга?

Убедитесь, что инициализация GTM идёт после навигации клиента, используйте хуки роутера или плагины, которые слушают смену роутов (app:mounted, router.afterEach).

Как подключить jQuery только на одной странице Nuxt-приложения?

На нужной странице используйте useHead или динамическую функцию loadScript в onMounted, убедившись, что скрипт не вставляется в head глобально (через nuxt.config). Так вы ограничите область видимости только нужной страницей.

Стрелочка влевоРуководство по использованию плагинов в NuxtГайд по Nuxt JS для начинающихСтрелочка вправо

Постройте личный план изучения Nuxt до уровня Middle — бесплатно!

Nuxt — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Nuxt

Генерация статического сайта с помощью NuxtКак использовать useAsyncData в NuxtКак использовать SVG в NuxtКоманды для запуска NuxtРабота с JSON-данными в NuxtКак настроить HTML-шаблон в NuxtГенерация статического сайта с помощью NuxtРуководство по получению данных с Fetch в NuxtКак отключить определенные функции в NuxtРабота с данными в Nuxt с помощью useNuxtDataНастройка и использование cookie в NuxtГайд по аутентификации (auth) в NuxtКак создавать API-маршруты в Nuxt
Использование Vite для ускорения разработки в NuxtРуководство по использованию TypeScript в NuxtКак запустить Nuxt-приложение в productionКак работает Server-Side Rendering SSR в NuxtНастройка и оптимизация серверной части Nuxt-приложенияРуководство по настройке маршрутизации в NuxtКакие проекты разумно реализовывать на NuxtИнструкция по управлению пакетами NPM в NuxtИнтеграция Node.js для Nuxt-приложенияНастройка мета-тегов для SEO в NuxtНастройка и использование HTTPS в NuxtКак отлавливать и обрабатывать ошибки в NuxtКак развернуть Nuxt приложение в DockerРуководство по развертыванию приложений в Nuxt CloudКак оптимизировать сборку на NuxtИнтеграция Laravel и Nuxt
Открыть базу знаний

Лучшие курсы по теме

Иконка ракетыСкоро!
изображение курса

Nuxt

Антон Ларичев
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий