Files
svg-sprites/skills/svg-sprites/src/ru/references/react-vite.md
S.Gromov 4833b31516 feat(skills): переработать AI-скиллы
- добавлены синхронные английские и русские инструкции для агентов
- расширена сборка документов из Markdown-фрагментов
- артефакты перенесены в игнорируемый release output
- обновлены README и проверки скиллов
2026-07-11 14:50:09 +03:00

9.5 KiB
Raw Blame History

React с Vite: операционный reference

Когда открывать

Открывай этот документ, если проект использует React без Next.js и собирается Vite, либо если generated-компонент содержит импорт sprite.svg?no-inline. Не применяй этот target к Webpack: для него открой react-webpack.md.

Сначала установи контекст

  1. Проверь package.json: должны быть React, Vite и фактические команды dev, build, typecheck.
  2. Найди существующие svg-sprite.config.ts и scripts с svg-sprites. Не создавай второй каталог для уже существующего спрайта.
  3. Выбери целевой каталог для конкретного спрайта. Это не обязан быть каталог module или feature: генератор принимает каталог с config, а не путь к самому config или icons/.
  4. Не редактируй вручную generated/, index.ts, manifest.ts и локальный .gitignore: ими владеет генератор.

Минимальная структура:

src/ui/file-manager/svg-sprite/
├── icons/
│   ├── check.svg
│   └── folder.svg
└── svg-sprite.config.ts

Настройка

src/ui/file-manager/svg-sprite/svg-sprite.config.ts:

export default {
  name: 'file-manager',
  description: 'Иконки файлового менеджера',
  inputFolder: './icons',
  inputFiles: ['../../../../shared/icons/check.svg'],
}
  • Для обычной CLI-генерации пакет устанавливать не нужно. Если он уже установлен локально ради SpriteViewer или программного API, defineReactSpriteConfig(...) можно использовать как необязательный helper для autocomplete.
  • Каждый такой config описывает один конкретный спрайт; в приложении может быть много независимых config и спрайтов.
  • Все пути в конфиге разрешаются относительно каталога svg-sprite.config.ts.
  • inputFolder по умолчанию равен ./icons; сканирование папки не рекурсивно и включает файлы с окончанием .svg.
  • inputFolder и inputFiles объединяются, одинаковый абсолютный путь дедуплицируется.
  • Если inputFiles заполнен, а неявного ./icons нет, генерация работает только по списку. Явно заданная отсутствующая inputFolder всегда является ошибкой.
  • Разные файлы с одинаковым basename, например два check.svg, конфликтуют как одно публичное имя иконки.
  • name должен быть kebab-case и начинаться с латинской буквы. FileManagerIcon, FileManagerIconName и fileManagerIconNames ниже — только пример generated-имён для name: 'file-manager'.
  • React preset всегда создаёт формат stack; выбрать symbol здесь нельзя.

Команда и scripts

Точная команда для примера выше:

npx --yes @gromlab/svg-sprites@latest --mode react@vite src/ui/file-manager/svg-sprite

Закрепи её в package.json и запускай до процессов, которым нужны generated imports:

{
  "scripts": {
    "sprite:file-manager": "npx --yes @gromlab/svg-sprites@latest --mode react@vite src/ui/file-manager/svg-sprite",
    "predev": "npm run sprite:file-manager",
    "prebuild": "npm run sprite:file-manager",
    "pretypecheck": "npm run sprite:file-manager"
  }
}

Если в проекте уже есть predev или prebuild, объедини команды в существующем orchestration вместо перезаписи script.

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

Импортируй только публичный локальный entry:

import { FileManagerIcon, fileManagerIconNames } from './svg-sprite'
import type { FileManagerIconName, FileManagerIconStyle } from './svg-sprite'

const colorStyle: FileManagerIconStyle = {
  '--icon-color-1': '#2563eb',
}

export function FolderIcon({ icon }: { icon: FileManagerIconName }) {
  return <FileManagerIcon icon={icon} className="icon" style={colorStyle} />
}

export const availableIcons = fileManagerIconNames

width и height в JSX необязательны: размер можно задать CSS-классом. Без wrapped компонент рендерит <svg> и принимает SVG attributes. С wrapped={true} корнем становится <span>, а внутренний SVG занимает его ширину и высоту:

<FileManagerIcon icon="folder" wrapped className="iconBox" />

Не делай deep import из generated/: структура generated-файлов не является точкой интеграции.

Нюанс target

Vite target генерирует статический импорт:

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

Query ?no-inline обязателен: он не даёт Vite превратить небольшой SVG в data URL. Не удаляй query и не копируй generated SVG в public; Vite должен выпустить отдельный asset с content hash.

Для низкоуровневого <use> применяй тот же механизм:

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

<svg className="icon">
  <use href={`${spriteUrl}#check`} />
</svg>

Ручной fragment #check безопасен только для имён вида ^[a-zA-Z][a-zA-Z0-9_-]*$. Для пробелов и других символов generated-компонент использует стабильный hash ID; точный ID находится в manifest.ts.

SpriteViewer

После генерации при необходимости установи пакет и добавь Viewer только на debug-маршрут:

npm install @gromlab/svg-sprites@latest
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 function IconsDebugPage() {
  return <SpriteViewer sources={sources} title="Иконки проекта" />
}

Аргумент import.meta.glob должен оставаться строковым литералом. Генерация обязана завершиться до старта Vite, иначе новые manifest.ts не попадут в glob.

Проверка результата

npm run sprite:file-manager
npm run typecheck

Это быстрые обязательные проверки. Проверь generated-файлы статически:

  • публичный index.ts экспортирует компонент, props, style, union имени и runtime-массив;
  • manifest.ts содержит target: "vite", format: "stack" и ожидаемое число иконок;

Если менялись target, asset pipeline или диагностируется runtime, дополнительно запусти production build. При наличии браузерных инструментов проверь Network: отдельный .svg asset вместо data:image/svg+xml, успешный URL и <use href="...svg#...">. Для сложных цветов, defs и размеров следуй complex-svg.md, не утверждая визуальный или a11y результат без доступных инструментов.

Типовые ошибки

  • React config file not found: в команду передан путь к icons/ или к файлу; передай каталог, содержащий svg-sprite.config.ts.
  • React mode requires a target: использован --mode react; нужен ровно react@vite.
  • Иконки нет в autocomplete: проверь case-sensitive окончание .svg, нерекурсивное расположение и повторно запусти генерацию до typecheck.
  • Refusing to overwrite a user file: не удаляй marker и не обходи writer; перенеси пользовательский файл или выбери другой sprite-каталог.
  • Viewer пуст: проверь строковый glob, существование generated manifest.ts и порядок запуска predev.
  • SVG оказался inline: проверь, что модуль сгенерирован target vite и импорт сохранил ?no-inline.
  • TypeScript не разрешает package subpath: используй TypeScript 5+ и moduleResolution: "bundler", "node16" или "nodenext".

Для запуска без CLI используй programmatic-api.md.