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

167 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# React с Vite: операционный reference
## Когда открывать
Открывай этот документ, если проект использует React без Next.js и собирается Vite, либо если generated-компонент содержит импорт `sprite.svg?no-inline`. Не применяй этот target к Webpack: для него открой [react-webpack.md](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`: ими владеет генератор.
Минимальная структура:
```text
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`:
```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
Точная команда для примера выше:
```bash
npx --yes @gromlab/svg-sprites@latest --mode react@vite src/ui/file-manager/svg-sprite
```
Закрепи её в `package.json` и запускай до процессов, которым нужны generated imports:
```json
{
"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:
```tsx
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 занимает его ширину и высоту:
```tsx
<FileManagerIcon icon="folder" wrapped className="iconBox" />
```
Не делай deep import из `generated/`: структура generated-файлов не является точкой интеграции.
## Нюанс target
Vite target генерирует статический импорт:
```ts
import spriteUrl from './sprite.svg?no-inline'
```
Query `?no-inline` обязателен: он не даёт Vite превратить небольшой SVG в data URL. Не удаляй query и не копируй generated SVG в `public`; Vite должен выпустить отдельный asset с content hash.
Для низкоуровневого `<use>` применяй тот же механизм:
```tsx
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-маршрут:
```bash
npm install @gromlab/svg-sprites@latest
```
```tsx
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.
## Проверка результата
```bash
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](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](programmatic-api.md).