Олег Марков
Использование 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:
- Минимизируйте количество сторонних скриптов. Каждый внешний скрипт увеличивает время загрузки страницы и может слабить защиту.
- Подключайте скрипты только там, где они нужны. Например, плагины оплаты — только на checkout.
- Используйте defer/async. Так вы ускоряете начальную загрузку страницы.
- Храните свои кастомные скрипты локально. Чтобы уменьшить зависимость от внешних сервисов.
- Следите за SEO-эффектами. Чрезмерное число скриптов или их неправильная загрузка ухудшают индексацию.
- Учитывайте работу с SSR. Скрипты, которым нужен access к window/document, подключайте только на клиенте (например, через плагин с .client.js).
- Используйте официальные 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 до уровня Middle — бесплатно!
Nuxt — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Nuxt
Лучшие курсы по теме

Nuxt
Антон Ларичев
TypeScript с нуля
Антон Ларичев