Files
svg-sprites/docs/ru/reference.md
S.Gromov 3f6b186a5b docs: переработать документацию проекта
- обновлены русская и английская версии README
- добавлены технические справочники на двух языках
- актуализированы ссылки и инструкции для React-сборок
2026-07-11 23:20:39 +03:00

20 KiB
Raw Permalink Blame History

Технический справочник

← Главная

Справочник по конфигурации, generated API и поведению @gromlab/svg-sprites. Пошаговую установку смотрите в руководстве для вашего стека:

Требования

  • Node.js 18 или новее;
  • пакет распространяется как ESM и подключается через import;
  • React 18 или 19 требуется для generated-компонентов и @gromlab/svg-sprites/react;
  • для типизации package exports используйте TypeScript 5+ с moduleResolution: "bundler", "node16" или "nodenext".

Пакет устанавливается как development dependency:

npm install --save-dev @gromlab/svg-sprites

CLI и режимы генерации

CLI принимает один режим и путь к каталогу конфигурации:

svg-sprites --mode <mode> <path>
Среда Mode
React + Vite react@vite
React + Webpack 5 react@webpack
Next.js App Router + Turbopack next@app/turbopack
Next.js App Router + Webpack 5 next@app/webpack
Next.js Pages Router + Turbopack next@pages/turbopack
Next.js Pages Router + Webpack 5 next@pages/webpack
Классические stack- и symbol-спрайты legacy

Современные React- и Next.js-режимы используют локальный svg-sprite.config.ts. Legacy-режим использует отдельный svg-sprites.config.ts и описан в собственном руководстве.

Mode должен соответствовать сборщику приложения. Генератор создаёт разный способ подключения SVG asset для Vite и сборщиков, совместимых с Webpack Asset Modules.

Конфигурация React и Next.js

Каждый каталог с svg-sprite.config.ts описывает один независимый спрайт.

import { defineNextSpriteConfig } from '@gromlab/svg-sprites'

export default defineNextSpriteConfig({
  name: 'app',
  description: 'Общие иконки приложения',
  inputFolder: './local-icons',
  inputFiles: [
    '../../assets/icons/search.svg',
    '../../assets/icons/settings.svg',
  ],
  transform: {
    removeSize: true,
    replaceColors: true,
    addTransition: true,
  },
  generatedNotice: true,
})

Для React используйте defineReactSpriteConfig. Контракт конфигурации одинаковый:

import { defineReactSpriteConfig } from '@gromlab/svg-sprites'
Опция Тип По умолчанию Назначение
name string Выводится из каталога Имя спрайта, компонента и публичных типов
description string Нет Описание для типов и debug manifest
inputFolder string ./icons Каталог с SVG относительно конфига
inputFiles string[] [] Пути к отдельным SVG относительно конфига
transform TransformOptions Все включены Настройки подготовки SVG
generatedNotice boolean true Полное или короткое предупреждение в generated-файлах

Имя спрайта

name записывается в kebab-case и должно начинаться с латинской буквы:

app          → AppIcon
file-manager → FileManagerIcon

Если name не задано, генератор выводит его из каталога. Для каталога с именем svg-sprite или svg-sprites используется имя родительского каталога.

Источники иконок

inputFolder и inputFiles объединяются в один набор. Это позволяет хранить локальные SVG рядом с модулем и добавлять общие иконки из других частей проекта без копирования.

Если inputFiles заполнен, а неявного каталога ./icons нет, генерация работает только по списку файлов. Явно указанная отсутствующая inputFolder считается ошибкой.

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

Одинаковые абсолютные пути дедуплицируются. Разные SVG с одинаковым именем файла считаются конфликтом, потому что публичное имя иконки выводится из basename.

Generated-модуль

После генерации каталог спрайта выглядит так:

app-icons/
├── .gitignore
├── index.ts
├── manifest.ts
├── svg-sprite.config.ts
└── generated/
    ├── .svg-sprites.manifest.json
    ├── react-component.tsx
    ├── sprite.svg
    ├── styles.module.css
    └── types.ts
Файл Назначение
index.ts Production exports компонента, props, стилей и имён иконок
manifest.ts Debug metadata и URL asset для SpriteViewer
generated/sprite.svg Собранный SVG-спрайт
generated/react-component.tsx Типизированный React-компонент
generated/styles.module.css Базовые стили и transitions
generated/types.ts Runtime-список и union-тип имён
generated/.svg-sprites.manifest.json Список файлов, которыми управляет генератор

Генератор перезаписывает и удаляет только файлы со своим marker. Если в managed-пути находится пользовательский файл, генерация завершается ошибкой.

React-компонент и TypeScript

Спрайт с name: 'app' экспортирует:

export { AppIcon, appIconNames }
export type { AppIconName, AppIconProps, AppIconStyle }

Имена иконок

Имена SVG-файлов становятся допустимыми значениями icon:

<AppIcon icon="search" />
<AppIcon icon="unknown" /> // ошибка TypeScript

Runtime-список содержит те же значения:

import { appIconNames } from '@/ui/app-icons'

// readonly ['search', 'settings', 'user']

Имена с пробелами и другими небезопасными для SVG ID символами остаются частью публичного API. Для внутреннего fragment ID генератор создаёт стабильный безопасный hash:

folder open.svg → icon="folder open" → id="icon-<stable-hash>"

Для таких имён используйте generated-компонент или id из debug manifest, а не формируйте fragment ID вручную.

SVG-атрибуты

По умолчанию компонент рендерит <svg> и принимает стандартные SVG-атрибуты:

<AppIcon
  icon="search"
  width={24}
  height={24}
  color="rebeccapurple"
  className="searchIcon"
  aria-label="Поиск"
/>

Компонент не добавляет accessibility-семантику автоматически. Передавайте подходящие aria-*, role или подпись в зависимости от назначения иконки.

Обёртка

wrapped рендерит <span> с внутренним SVG. Остальные props в этом режиме относятся к <span>:

<AppIcon icon="search" wrapped className="iconWrapper" />

Типизированные CSS-переменные

AppIconStyle расширяет CSSProperties и поддерживает свойства вида --icon-color-N:

<AppIcon
  icon="user"
  style={{
    '--icon-color-1': '#2563eb',
    '--icon-color-2': '#dbeafe',
  }}
/>

Множественные спрайты

Каждый каталог с конфигом создаёт независимый компонент, типы, manifest и SVG asset:

app-icons       → AppIcon       → общие иконки
analytics-icons → AnalyticsIcon → иконки страницы аналитики
editor-icons    → EditorIcon    → иконки редактора

Один исходный SVG можно добавить через inputFiles в несколько конфигураций. Копировать файл в каталоги каждого спрайта не требуется.

Для нескольких спрайтов добавьте отдельную CLI-команду для каждого каталога или объедините команды в общем npm script.

Форматы и способы отображения

Современные React- и Next.js-режимы создают формат stack. Legacy-режим поддерживает stack и symbol.

Формат <svg><use> <img> CSS background
stack Да Да Да
symbol Да Нет Нет

Generated-компонент

Для React и Next.js используйте generated-компонент. Он знает внутренние ID, формирует URL и предоставляет TypeScript API:

<AppIcon icon="search" width={24} height={24} />

Вручную через <svg><use>

Способ получения spriteUrl зависит от сборщика.

Vite:

import spriteUrl from './generated/sprite.svg?no-inline'

Webpack 5, Turbopack и Next.js:

const spriteUrl = new URL('./generated/sprite.svg', import.meta.url).href

После получения URL используйте его в JSX:

<svg width="24" height="24" aria-label="Поиск">
  <use href={`${spriteUrl}#search`} />
</svg>

Для имён, небезопасных как SVG ID, используйте внутренний id из manifest.

Через <img>

<img src={`${spriteUrl}#search`} width={24} height={24} alt="Поиск" />

SVG внутри <img> изолирован от CSS страницы. color и --icon-color-N на внешнем элементе не изменяют его внутренние цвета.

Через CSS

.icon {
  background: url('./generated/sprite.svg#search') center / contain no-repeat;
}

Для одноцветного силуэта можно использовать mask:

.icon {
  background-color: currentColor;
  mask: url('./generated/sprite.svg#search') center / contain no-repeat;
}

Mask не сохраняет исходные цвета, gradients и различия между fill и stroke.

Путь в CSS разрешается относительно самого CSS-файла. В примерах CSS-файл находится рядом с svg-sprite.config.ts.

Assets и кеширование

Generated-компонент передаёт SVG сборщику как отдельный asset:

  • Vite использует статический импорт с ?no-inline;
  • Webpack 5, Turbopack и Next.js используют new URL(..., import.meta.url);
  • SVG path-данные не сериализуются в generated TSX.

При стандартном именовании assets сборщик добавляет content hash:

/assets/sprite-<hash>.svg

Это позволяет кешировать SVG отдельно от JavaScript. Изменение React-кода не меняет содержимое спрайта, а изменение иконок создаёт новую версию asset.

HTTP cache headers, CDN и Cache-Control настраиваются приложением или платформой размещения. Для Webpack имя итогового файла зависит от assetModuleFilename проекта.

Трансформации SVG

Все трансформации включены по умолчанию и настраиваются независимо:

Опция Что делает
removeSize Удаляет width и height с корневого <svg>, сохраняя существующий viewBox
replaceColors Заменяет найденные fill и stroke на --icon-color-N
addTransition Добавляет transitions для fill и stroke в цветные элементы и generated styles

Чтобы отключить отдельную операцию:

export default defineNextSpriteConfig({
  transform: {
    removeSize: false,
    replaceColors: false,
    addTransition: false,
  },
})

Исходные SVG не изменяются. Трансформации применяются только к содержимому generated-спрайта.

Управление цветами

Монохромные иконки

Если найден один цвет, fallback становится currentColor:

stroke="var(--icon-color-1, currentColor)"

Цвет задаётся через prop или CSS:

<AppIcon icon="search" color="rebeccapurple" />

Многоцветные иконки

Каждый уникальный цвет получает отдельную переменную с исходным fallback:

fill="var(--icon-color-1, #798198)"
fill="var(--icon-color-2, #ffffff)"
fill="var(--icon-color-3, #129d9d)"

Можно заменить только необходимые значения:

.icon {
  --icon-color-1: #4b5563;
  --icon-color-3: #14b8a6;
}

Ограничения

  • none, transparent, inherit, unset и initial не заменяются;
  • надёжнее всего обрабатываются цвета в атрибутах fill, stroke и inline style;
  • CSS-классы и внешние stylesheets внутри SVG не являются основным сценарием трансформации;
  • значения url(#...) могут быть заменены вместе с цветами, поэтому gradients и patterns требуют отдельного спрайта с replaceColors: false;
  • masks, filters и сложные внутренние CSS-правила требуют визуальной проверки;
  • CSS-переменные страницы доступны через <svg><use>, но не внутри <img> и CSS background.

Для сложной иконки можно отключить replaceColors в конфигурации отдельного спрайта.

SpriteViewer

SpriteViewer подключается из отдельной клиентской точки входа:

import { SpriteViewer } from '@gromlab/svg-sprites/react'

Он принимает готовые manifests, массив lazy loaders или record формата import.meta.glob.

Vite:

import { SpriteViewer } from '@gromlab/svg-sprites/react'
import type { SpriteManifestModule } from '@gromlab/svg-sprites/react'

const sources = import.meta.glob<SpriteManifestModule>(
  '/src/**/svg-sprite/manifest.ts',
)

export const IconsDebugPage = () => (
  <SpriteViewer sources={sources} title="Иконки проекта" />
)

Webpack и Next.js:

const sources = [
  () => import('@/ui/app-icons/manifest'),
  () => import('@/features/analytics/icons/manifest'),
]

export const IconsDebugPage = () => (
  <SpriteViewer sources={sources} />
)

Viewer показывает группы, поиск, viewBox, CSS-переменные, fallback-цвета и примеры React, SVG, IMG и CSS. Цветовые значения можно менять в интерфейсе и сразу проверять результат.

Тема Viewer

По умолчанию colorTheme="auto" следует prefers-color-scheme. Можно передать light или dark явно:

<SpriteViewer sources={sources} colorTheme="dark" />

Для синхронизации с темой приложения:

<SpriteViewer
  sources={sources}
  colorTheme={appTheme}
  onColorThemeChange={setAppTheme}
/>

@gromlab/svg-sprites/react содержит 'use client'. В Next.js App Router размещайте Viewer внутри отдельной Client Component boundary и используйте только на debug-маршруте или во внутреннем инструменте.

Generated-файлы, Git и CI

Современный sprite-модуль создаёт локальный .gitignore для:

/generated/
/index.ts
/manifest.ts

Локальный .gitignore следует один раз добавить в репозиторий. Он исключает остальные generated-файлы, поэтому генерацию нужно запускать перед командами, которые импортируют sprite-модуль:

{
  "scripts": {
    "sprites": "svg-sprites --mode next@app/turbopack src/ui/app-icons",
    "predev": "npm run sprites",
    "prebuild": "npm run sprites",
    "pretypecheck": "npm run sprites"
  }
}

CI должен устанавливать development dependencies и выполнять generation script до сборки или проверки типов.

Если в каталоге спрайта уже находится пользовательский .gitignore, index.ts или manifest.ts, генератор не перезапишет его. Переместите пользовательский файл или выберите отдельный каталог спрайта.

Диагностика

  • Нет index.ts: запустите generation script до импорта модуля.
  • Не найдена конфигурация: проверьте путь CLI и имя svg-sprite.config.ts.
  • Иконка отсутствует в типе: проверьте inputFiles, расширение .svg и уровень вложенности inputFolder.
  • Конфликт имени: два разных SVG имеют одинаковый basename; переименуйте один файл.
  • Refusing to overwrite a user file: в managed-пути находится файл без generated marker.
  • Иконка не меняет цвет: используйте <svg><use> или generated-компонент и проверьте replaceColors.
  • Webpack выдаёт неверный URL: проверьте Asset Modules, output.publicPath и SVG loaders.
  • Viewer не видит спрайт: проверьте путь к manifest.ts и выполните генерацию до запуска приложения.
  • Build и mode не совпадают: используйте target, соответствующий фактическому сборщику.

Для собственного orchestration и низкоуровневой компиляции смотрите Программный API.