Олег Марков
Использование 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 с нуля
Антон Ларичев