- добавлены синхронные английские и русские инструкции для агентов - расширена сборка документов из Markdown-фрагментов - артефакты перенесены в игнорируемый release output - обновлены README и проверки скиллов
9.5 KiB
React с Vite: операционный reference
Когда открывать
Открывай этот документ, если проект использует React без Next.js и собирается Vite, либо если generated-компонент содержит импорт sprite.svg?no-inline. Не применяй этот target к Webpack: для него открой react-webpack.md.
Сначала установи контекст
- Проверь
package.json: должны быть React, Vite и фактические командыdev,build,typecheck. - Найди существующие
svg-sprite.config.tsи scripts сsvg-sprites. Не создавай второй каталог для уже существующего спрайта. - Выбери целевой каталог для конкретного спрайта. Это не обязан быть каталог module или feature: генератор принимает каталог с config, а не путь к самому config или
icons/. - Не редактируй вручную
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.