Олег Марков
Как использовать SVG в Nuxt
Введение
SVG — это масштабируемый векторный формат для отображения графики прямо в браузере. Его применяют для иконок, иллюстраций, сложных диаграмм и визуальных эффектов, потому что изображения не теряют качества при масштабировании. В Nuxt, современном фреймворке для создания приложений на Vue, разработчики нередко сталкиваются с задачей интеграции SVG-графики. Здесь я объясню, как именно это реализовать, какие подходы существуют и что выбрать для конкретных задач. Разберем плюсы и минусы, приведу наглядные примеры из реальных проектов и объясню, как свести к минимуму рутину при работе с SVG.
Использование SVG-файлов в Nuxt
В Nuxt поддержка SVG возможна различными способами — от простого добавления через тег img до инлайна по средствам плагинов и модификации webpack-конфига. Рассмотрим их поэтапно.
Использование SVG позволяет создавать масштабируемую и векторную графику для ваших Nuxt-приложений. Однако для эффективного использования SVG необходимо понимать, как работают векторные изображения, как оптимизировать SVG-файлы и как интегрировать их с вашими компонентами. Если вы хотите углубить свои знания об использовании SVG в Nuxt, приходите на наш большой курс Nuxt - fullstack Vue фреймворк. На курсе 129 уроков и 13 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.
Вариант 1. Использование SVG как URL
Начнем с самого простого способа. Допустим, у вас есть иконка logo.svg
в папке static. Ваш Nuxt проект устроен так, что все, что лежит в папке static
, будет раздаваться как статика без обработки.
Пример использования:
html
<template>
<div>
<img src="/logo.svg" alt="Логотип" />
</div>
</template>
Здесь мы просто ссылаемся на файл в папке static. Этот способ понятен и работает для большинства базовых кейсов.
Недостатки:
- Вы не сможете кастомизировать svg напрямую (например, манипулировать цветом за счет привязки CSS).
- SVG не становится частью DOM, а значит, анимации, динамические изменения и доступность для тестов сильно ограничены.
Вариант 2. Инлайновая встраиваемая SVG
Когда вам нужно больше контроля над SVG (смена цвета иконки через props, добавление обработчиков событий и т.д.), лучше использовать инлайновое подключение SVG прямо в шаблоне компонента.
Пример:
html
<template>
<svg width="40" height="40" viewBox="0 0 40 40" fill="none">
<circle cx="20" cy="20" r="18" stroke="blue" stroke-width="4" />
</svg>
</template>
Преимущества:
- SVG становится частью HTML и управляется через JavaScript и CSS.
- Можно динамически менять атрибуты прямо через props.
Минусы:
- При большом числе SVG их код может засорять шаблоны Nuxt-компонентов.
- Нет удобной возможности переиспользования между разными компонентами без вынесения SVG в отдельные компоненты.
Вариант 3. Хранение SVG-файлов в assets и импорт через require или import
Nuxt автоматически поддерживает загрузку ресурсов из папки assets
, которую чаще используют для SCSS-соединений, картинок и т.д. Однако SVG из assets не доступны напрямую по URL. Их приходится импортировать, и тут уже можно применить загрузчики webpack.
Пример:
```html
**Комментарий:**
Здесь SVG подключен как изображение, а не внедрен в DOM, поэтому кастомизация ограничена.
Чтобы получить доступ к svg-разметке, можно воспользоваться специальным загрузчиком, например [vue-svg-loader](https://github.com/vuejs/vue-svg-loader).
### Вариант 4. Использование vue-svg-loader для инлайна SVG как компонентов
Этот подход позволяет обрабатывать SVG как полноценные Vue-компоненты, а значит динамика, кастомизация и переиспользование становятся очень простыми.
#### Установка и настройка vue-svg-loader
1. Установите загрузчик:
bash
npm install -D vue-svg-loader
2. Добавьте настройку в ваш nuxt.config.js:
js
export default {
build: {
extend(config) {
// Удаляем стандартную обработку для svg, чтобы не было конфликтов
const svgRule = config.module.rules.find(rule =rule.test && rule.test.test('.svg')) if (svgRule) { svgRule.exclude = [/assets/svg/] }
// Добавляем новое правило
config.module.rules.push({
test: /\.svg$/,
include: [/assets\/svg/], // Подключаем только определенную папку
use: [
'babel-loader',
{
loader: 'vue-svg-loader',
options: {
svgo: {
plugins: [
{ removeViewBox: false }
]
}
}
}
]
})
}
}
} ```
Создайте папку
assets/svg
и поместите SVG-файлы туда.Импортируйте SVG, как обычный компонент:
Пример:
```html
**Комментарий:**
Теперь можно менять наполнение SVG, стилизовать через class и даже передавать события.
`vue-svg-loader` позволяет использовать SVG как части шаблонов, объекты наследуют все возможности Vue-компонентов.
**Преимущества:**
- Full-привязка ко всем возможностям Vue.
- Простота переиспользования SVG как компонентов.
- Быстрая стилизация и замена свойств через props/slot.
**Обратите внимание:**
По умолчанию Nuxt может выбирать разный loader для svg в зависимости от вашей версии. Если что-то идет не по плану — проверьте порядок правил webpack.
### Вариант 5. Плагины для автоматизации SVG-иконок (например, unplugin-icons)
В Nuxt-проектах часто нужно использовать большую библиотеку иконок с возможностью их подгрузки "на лету". Для этого подходят плагины вроде [unplugin-icons](https://github.com/unplugin/unplugin-icons).
#### Быстрый старт с unplugin-icons
1. Установите плагин:
bash
npm install -D unplugin-icons @iconify/json
2. Добавьте плагин в Nuxt:
js
// nuxt.config.js import Icons from 'unplugin-icons/vite' export default { vite: { plugins: [ Icons({ compiler: 'vue3', autoInstall: true }) ] } } ```
- Используйте иконки прямо в шаблоне:
<template>
<div>
<i-heroicons-outline-home class="icon" />
</div>
</template>
В этом примере i-heroicons-outline-home
— это иконка из heroicons, которую вы вызываете по алиасу, не заботясь о подключении файла.
Достоинства:
- Сотни иконок "из коробки".
- Можно добавить свои иконки в виде svg.
- Сжатие, оптимизация и загрузка только используемых иконок.
Совет:
Если в проекте много SVG-иконок, попробуйте unplugin-icons или аналогичные решения — это сразу улучшает “девелоперский опыт”.
Вариант 6. Оптимизация SVG (svgo, vite-plugin-svg-sprite)
SVG могут быть избыточными из-за лишних атрибутов, ненужных тегов или комментариев внутри файла. Оптимизировать их лучше до того, как вы начнете работать с ними в Nuxt.
SVGO — инструмент для оптимизации
Установите глобально или в проект:
bash
npm install -D svgo
Затем запускайте:
bash
npx svgo assets/svg/logo.svg -o assets/svg/logo.optimized.svg
vite-plugin-svg-sprite для Nuxt 3
Если вы на Nuxt 3, можно использовать сразу svg-спрайты:
npm install -D vite-plugin-svg-sprite
Пример конфигурации:
js
// nuxt.config.js
import svgSpritePlugin from 'vite-plugin-svg-sprite'
export default {
vite: {
plugins: [
svgSpritePlugin({
symbolId: 'icon-[name]'
})
]
}
}
Затем в шаблоне:
html
<svg>
<use xlink:href="#icon-logo" />
</svg>
Здесь вы можете быстро обращаться к иконкам и использовать их как sprite, что экономит трафик и повышает производительность.
Вариант 7. Использование Nuxt Content для SVG (Markdown)
Если вы пишете документацию или блог на Nuxt Content, можно вставлять SVG прямо в Markdown.

SVG попадет как обычное изображение. Но учтите: инлайн-директива тут, как правило, невозможна без настройки markdown-it.
Выбор подхода — что использовать и когда
- Для статических изображений, иллюстраций и баннеров — используйте
<img src="...">
или Vite asset imports. - Для иконок, которые нужно стилизовать в зависимости от состояния — инлайн SVG через vue-svg-loader или unplugin-icons.
- Для коллекций иконок и оптимизации отдачи — попробуйте sptrie-решения и плагины.
- Для markdown/контента — простой URL или Markdown link.
SVG и доступность (a11y)
Обратите внимание: SVG не всегда доступны по умолчанию. Всегда добавляйте атрибуты aria-label
и role="img"
, если иконка несет смысловую нагрузку.
Пример:
html
<svg role="img" aria-label="Логотип компании">
<!-- ... -->
</svg>
Если это purely декоративные элементы, используйте aria-hidden="true"
и убирайте из фокуса.
Пример:
html
<svg aria-hidden="true" focusable="false">
<!-- ... -->
</svg>
Это особенно важно, если вы делаете интерфейсы для широкой аудитории.
Организация SVG-файлов и компонентов
Храните SVG-иконки в отдельной папке. Если вы делаете свой набор иконок, создайте структуры:
assets/svg
для файловcomponents/icons
для Vue-оберток
Для общего переиспользования заведите компонент Icon:
<template>
<component :is="iconComponent" v-bind="$attrs" />
</template>
<script>
export default {
props: {
name: {
type: String,
required: true
}
},
computed: {
iconComponent() {
// Кешируйте здесь маппинг ваших иконок
const icons = {
logo: () => import('~/assets/svg/logo.svg'),
user: () => import('~/assets/svg/user.svg')
}
return icons[this.name] || null
}
}
}
</script>
Такой конструктор позволяет по атрибуту передавать нужную иконку и отображать ее.
Заключение
Nuxt позволяет гибко интегрировать SVG графику в проекты: можно использовать простые теги <img>
, инлайновое подключение svg-кода, специальные загрузчики для импорта SVG как компонента, а также автоматизировать сборку и использование множества иконок с помощью плагинов. Для каждого варианта есть свои особенности и рекомендуемые сценарии, а оптимальные подходы зависят от ваших целей — универсальной библиотеки иконок, уникальных иллюстраций или сложной визуализации прямо в DOM. Внимательно отнеситесь к аспектам доступности и не забывайте оптимизировать SVG перед загрузкой в проект.
Работа с графикой и изображениями - это важный аспект веб-разработки. Чтобы создавать гибкие и масштабируемые приложения, необходимо освоить все возможности фреймворка, включая работу с сервером, базами данных и API. На нашем курсе Nuxt - fullstack Vue фреймворк вы найдете все необходимые знания и навыки для достижения успеха. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в Nuxt прямо сегодня.
Частозадаваемые технические вопросы по теме статьи и ответы на них
1. Почему svg-файл не стилизуется через CSS, когда я использую тег img?
> SVG, подключенный через <img src="..." />
, не становится частью DOM и не может быть стилизован напрямую через внешние CSS классы. Чтобы управлять стилями, импортируйте SVG как компонент с помощью vue-svg-loader или вставляйте его инлайном.
2. Как оптимизировать размер SVG перед подключением в Nuxt?
> Используйте инструмент svgo: установите через npm npm install -D svgo
и оптимизируйте файлы командой npx svgo путь_к_файлу.svg
. Это уменьшит размер svg и ускорит загрузку страницы.
3. Можно ли анимировать SVG, импортированный как компонент через vue-svg-loader? > Да, анимации доступны. Добавляйте анимации через CSS (например, к отдельным слоям SVG), либо используйте Vue props и директивы, чтобы управлять анимацией из родительского компонента.
4. Почему не работает импорт SVG через import в Nuxt 3? > В Nuxt 3 по умолчанию изменены настройки загрузчиков. Добавьте нужный загрузчик для SVG (например, vite-plugin-svg или настройте vue-svg-loader), а для индивидуальных требований проверьте схему asset imports в документации Nuxt.
5. Как добавить пользовательские наборы SVG-иконок для использования в unplugin-icons? > Для этого создайте собственную директорию с вашими SVG, настройте плагин unplugin-icons на считывание этих файлов и используйте схему алиасов. В документации плагина есть конкретные примеры по созданию кастомных коллекций.
Постройте личный план изучения Nuxt до уровня Middle — бесплатно!
Nuxt — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Nuxt
Лучшие курсы по теме

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