mirror of
https://github.com/gromlab-ru/svg-sprites.git
synced 2026-07-22 04:40:17 +03:00
feat: добавить серверную генерацию спрайтов
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
Общий формат JSON, JavaScript и TypeScript config-файлов описан в [руководстве по конфигурации](configuration.md).
|
||||
|
||||
## Гайды быстрого старта
|
||||
## Быстрый старт для consumer modes
|
||||
|
||||
| Проект | Exact mode | Guide |
|
||||
|---|---|---|
|
||||
@@ -39,12 +39,16 @@
|
||||
| Next.js Pages Router + Turbopack | `next@pages/turbopack` | [Pages Router + Turbopack](guides/next-pages-turbopack.md) |
|
||||
| Next.js Pages Router + Webpack | `next@pages/webpack` | [Pages Router + Webpack](guides/next-pages-webpack.md) |
|
||||
|
||||
Все guides используют один порядок:
|
||||
Все consumer guides используют один порядок:
|
||||
|
||||
1. Генерация спрайта через `npx` без добавления package в проект.
|
||||
2. Использование спрайта в приложении.
|
||||
3. Необязательное подключение Viewer для дебага и превью.
|
||||
|
||||
## Серверная генерация
|
||||
|
||||
Используйте [`standalone@server`](guides/standalone-server.md), чтобы сгенерировать на сервере или в CI/CD универсальный SVG-спрайт для всех consumer modes.
|
||||
|
||||
## Справочники
|
||||
|
||||
- [Конфигурация](configuration.md)
|
||||
|
||||
@@ -32,6 +32,7 @@ JSON подходит для большинства проектов и не т
|
||||
| Поле | По умолчанию | Назначение |
|
||||
|---|---|---|
|
||||
| `mode` | Нет | Exact mode, соответствующий framework и сборщику |
|
||||
| `source` | `local` | `local` для исходных SVG или `remote` для manifest от `standalone@server` |
|
||||
| `name` | Kebab-case имени каталога модуля; для `svg-sprite` и `svg-sprites` — имени родительского каталога | Имя спрайта; в modes с компонентом также задаёт имя компонента и типов |
|
||||
| `description` | Нет | Описание для типов и Viewer |
|
||||
| `input` | `./icons` | Каталог, SVG-файл, glob-шаблон или массив источников |
|
||||
@@ -40,6 +41,45 @@ JSON подходит для большинства проектов и не т
|
||||
|
||||
Пути и glob-шаблоны в `input` считаются от каталога config-файла. Паттерн с префиксом `!` исключает совпадения.
|
||||
|
||||
## Удалённо собранный спрайт
|
||||
|
||||
Consumer config для server manifest содержит только mode, source и input:
|
||||
|
||||
```json
|
||||
{
|
||||
"mode": "react@vite",
|
||||
"source": "remote",
|
||||
"input": "https://assets.example/releases/app/svg-sprite.manifest.json"
|
||||
}
|
||||
```
|
||||
|
||||
`input` принимает один HTTP(S) URL или локальный путь к manifest. Имя, описание,
|
||||
transforms и generated notice берутся из manifest. Генератор скачивает и проверяет
|
||||
подходящий SVG profile, после чего adapter создаёт обычные локальные компоненты,
|
||||
типы и asset для сборщика.
|
||||
|
||||
## Серверная сборка
|
||||
|
||||
`standalone@server` объединяет local paths/globs и HTTP(S) SVG descriptors:
|
||||
|
||||
```js
|
||||
export default {
|
||||
mode: 'standalone@server',
|
||||
name: 'app',
|
||||
input: [
|
||||
'./icons/**/*.svg',
|
||||
{
|
||||
name: 'remote-logo',
|
||||
url: 'https://assets.example/logo.svg',
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Mode создаёт два content-addressed SVG profiles и `svg-sprite.manifest.json`.
|
||||
`sha256` у HTTP input необязателен; если он указан, это должен быть ожидаемый
|
||||
64-символьный hexadecimal SHA-256 digest, по которому сборка проверит полученные байты.
|
||||
|
||||
## JavaScript
|
||||
|
||||
JavaScript-конфиг экспортирует обычный объект по умолчанию:
|
||||
|
||||
@@ -30,13 +30,19 @@
|
||||
|
||||
Пути, имена, команды, импорты и названия сгенерированных API должны соответствовать друг другу и фактическому результату генерации.
|
||||
|
||||
Во всех гайдах используются согласованные примеры:
|
||||
Во всех consumer-гайдах используются согласованные примеры:
|
||||
|
||||
- исходные SVG находятся в `assets/svg-icons`;
|
||||
- спрайт создаётся в `assets/app-icons`;
|
||||
- конфиг записывается в JSON;
|
||||
- имя спрайта в конфиге — `app`.
|
||||
|
||||
`standalone@server` является исключением: quick start использует config-less CLI,
|
||||
исходные SVG находятся в `./icons` временного worker workspace, output создаётся в
|
||||
текущем каталоге, а mode, name и input передаются флагами одной команды. Server
|
||||
config упоминается только как дополнительный вариант; подключение из consumer
|
||||
может использовать обычный JSON config соответствующего mode.
|
||||
|
||||
## Зависимости
|
||||
|
||||
В разделе генерации нужно явно показать ключевое преимущество: для создания и использования спрайта пакет не требуется добавлять в зависимости проекта.
|
||||
@@ -48,7 +54,7 @@ Viewer описывается отдельно как необязательны
|
||||
Гайд должен содержать только минимальный рабочий путь:
|
||||
|
||||
- структуру проекта;
|
||||
- конфиг;
|
||||
- конфиг либо полный config-less CLI-вызов для `standalone@server`;
|
||||
- команду генерации;
|
||||
- автоматическую генерацию перед запуском и сборкой, если она необходима;
|
||||
- подключение иконки;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Гайды быстрого старта
|
||||
|
||||
## Consumer-приложения
|
||||
|
||||
- `standalone`: [bare standalone](standalone.md)
|
||||
- `standalone@vite`: [standalone с Vite](standalone-vite.md)
|
||||
- `standalone@webpack`: [standalone с Webpack](standalone-webpack.md)
|
||||
@@ -29,3 +31,7 @@
|
||||
- `next@app/webpack`: [App Router с Webpack](next-app-webpack.md)
|
||||
- `next@pages/turbopack`: [Pages Router с Turbopack](next-pages-turbopack.md)
|
||||
- `next@pages/webpack`: [Pages Router с Webpack](next-pages-webpack.md)
|
||||
|
||||
## Серверная генерация
|
||||
|
||||
- `standalone@server`: [сгенерировать универсальный спрайт на сервере](standalone-server.md)
|
||||
|
||||
113
docs/ru/guides/standalone-server.md
Normal file
113
docs/ru/guides/standalone-server.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# Универсальный SVG-спрайт на сервере
|
||||
|
||||
Сгенерируйте в CI или server worker универсальный SVG-спрайт, который смогут использовать приложения с разными frameworks и bundlers.
|
||||
|
||||
## Генерация спрайта
|
||||
|
||||
Устанавливать пакет в worker не нужно.
|
||||
|
||||
### 1. Подготовьте рабочий каталог
|
||||
|
||||
Поместите исходные SVG в папку `icons` текущего workspace:
|
||||
|
||||
```text
|
||||
.
|
||||
└── icons/
|
||||
├── search.svg
|
||||
└── settings.svg
|
||||
```
|
||||
|
||||
Имена файлов без расширения станут именами иконок.
|
||||
|
||||
### 2. Запустите генерацию
|
||||
|
||||
Передайте mode, имя спрайта и путь к SVG через CLI:
|
||||
|
||||
```bash
|
||||
npx --yes @gromlab/svg-sprites \
|
||||
--mode standalone@server \
|
||||
--name app \
|
||||
--input './icons/**/*.svg' \
|
||||
.
|
||||
```
|
||||
|
||||
Config-файл для этого worker-сценария не нужен. Результат появится в `./.svg-sprite`:
|
||||
|
||||
```text
|
||||
.
|
||||
├── icons/
|
||||
│ ├── search.svg
|
||||
│ └── settings.svg
|
||||
└── .svg-sprite/
|
||||
├── sprite.<content-hash>.svg
|
||||
├── sprite-root-viewbox.<content-hash>.svg
|
||||
└── svg-sprite.manifest.json
|
||||
```
|
||||
|
||||
### 3. Опубликуйте результат
|
||||
|
||||
Загрузите содержимое `.svg-sprite` в отдельный каталог S3 bucket:
|
||||
|
||||
```bash
|
||||
aws s3 sync ./.svg-sprite/ s3://my-bucket/app-icons/
|
||||
```
|
||||
|
||||
Этот же каталог можно раздавать через CDN. В публичном URL нет сегмента `.svg-sprite`:
|
||||
|
||||
```text
|
||||
https://cdn.example.com/app-icons/
|
||||
├── sprite.<content-hash>.svg
|
||||
├── sprite-root-viewbox.<content-hash>.svg
|
||||
└── svg-sprite.manifest.json
|
||||
```
|
||||
|
||||
`standalone@server` также можно запускать через JSON, JavaScript или TypeScript config. Config подходит для постоянных настроек, локальных SVG из нескольких каталогов и SVG, загружаемых по HTTP(S).
|
||||
|
||||
## Использование спрайта
|
||||
|
||||
В consumer-приложении создайте обычный config. Например, для React с Vite:
|
||||
|
||||
```text
|
||||
src/app-icons/
|
||||
├── index.ts
|
||||
└── svg-sprite.config.json
|
||||
```
|
||||
|
||||
Укажите consumer mode и URL manifest из CDN:
|
||||
|
||||
```json
|
||||
{
|
||||
"mode": "react@vite",
|
||||
"source": "remote",
|
||||
"input": "https://cdn.example.com/app-icons/svg-sprite.manifest.json"
|
||||
}
|
||||
```
|
||||
|
||||
Добавьте пользовательскую точку входа:
|
||||
|
||||
```ts
|
||||
// src/app-icons/index.ts
|
||||
export * from './.svg-sprite/index.js'
|
||||
```
|
||||
|
||||
Запустите обычную генерацию:
|
||||
|
||||
```bash
|
||||
npx --yes @gromlab/svg-sprites src/app-icons/svg-sprite.config.json
|
||||
```
|
||||
|
||||
После этого используйте generated-компонент так же, как со спрайтом из локальных SVG:
|
||||
|
||||
```tsx
|
||||
import { AppIcon } from './app-icons'
|
||||
|
||||
export function SearchButton() {
|
||||
return <AppIcon icon="search" aria-label="Поиск" />
|
||||
}
|
||||
```
|
||||
|
||||
Тот же CDN manifest поддерживают все 29 consumer modes. В каждом из них сохраняется нативный API выбранного framework и bundler.
|
||||
|
||||
## Дебаг и превью
|
||||
|
||||
`standalone@server` не создаёт отдельную страницу для просмотра иконок. Подключите опубликованный спрайт к consumer-приложению и откройте его в SpriteViewer: удалённый набор будет отображаться так же, как локальный.
|
||||
@@ -27,7 +27,9 @@ result.spritePath
|
||||
result.manifestPath
|
||||
```
|
||||
|
||||
Next.js modes дополнительно возвращают `router` и `bundler`.
|
||||
Next.js modes дополнительно возвращают `router` и `bundler`. `standalone@server`
|
||||
возвращает `target: 'server'`; его `spritePath` указывает на стандартный
|
||||
content-addressed profile, а `manifestPath` — на server manifest.
|
||||
|
||||
Для static standalone mode `result.spritePath` можно использовать в build-скрипте,
|
||||
чтобы опубликовать SVG по URL приложения:
|
||||
@@ -102,6 +104,11 @@ export default defineSpriteConfig({
|
||||
|
||||
`defineSpriteConfig` является identity helper для TypeScript autocomplete. JS может экспортировать тот же объект через `export default`, а JSON содержит объект непосредственно.
|
||||
|
||||
Публичные типы `ServerSvgInput`, `ServerSpriteManifest`, `ServerSpriteAsset` и
|
||||
`SpriteCompileProfile` описывают inputs и release data для `standalone@server`.
|
||||
Consumer использует тот же API с `source: 'remote'` и одним local path или HTTP(S)
|
||||
URL manifest в `input`.
|
||||
|
||||
## Специализированные обёртки
|
||||
|
||||
Специализированные функции доступны как обёртки над `generateSprite`:
|
||||
|
||||
@@ -69,6 +69,7 @@ svg-sprites [options] <config-file-or-directory>
|
||||
| Static HTML / собственная публикация | `standalone` |
|
||||
| Standalone + Vite | `standalone@vite` |
|
||||
| Standalone + Webpack 5 | `standalone@webpack` |
|
||||
| Server release | `standalone@server` |
|
||||
| React + Vite | `react@vite` |
|
||||
| React + Webpack 5 | `react@webpack` |
|
||||
| Vue + Vite | `vue@vite` |
|
||||
@@ -100,7 +101,7 @@ Config-файл может иметь любое имя и расширение
|
||||
|
||||
Если передан каталог, все настройки берутся из CLI. Если передан config-файл, CLI-параметры перекрывают значения файла. Общий порядок: `defaults → config → CLI`.
|
||||
|
||||
`--help` и `-h` выводят справку без обязательного пути. Для генерации доступны `--mode`, `--name`, `--description`, повторяемый `--input <path-or-glob>`, а также пары `--remove-size`/`--no-remove-size`, `--replace-colors`/`--no-replace-colors`, `--add-transition`/`--no-add-transition` и `--generated-notice`/`--no-generated-notice`. Переданные transform-флаги перекрывают отдельные поля, а хотя бы один `--input` полностью заменяет значение `input` из config.
|
||||
`--help` и `-h` выводят справку без обязательного пути. Для генерации доступны `--mode`, `--source <local|remote>`, `--name`, `--description`, повторяемый `--input <path-or-glob>`, а также пары `--remove-size`/`--no-remove-size`, `--replace-colors`/`--no-replace-colors`, `--add-transition`/`--no-add-transition` и `--generated-notice`/`--no-generated-notice`. Переданные transform-флаги перекрывают отдельные поля, а хотя бы один `--input` полностью заменяет значение `input` из config.
|
||||
|
||||
В CLI заключайте glob-паттерны в одинарные кавычки, чтобы shell не раскрыл их до запуска генератора:
|
||||
|
||||
@@ -138,12 +139,20 @@ export default defineSpriteConfig({
|
||||
| Опция | Тип | По умолчанию | Назначение |
|
||||
|---|---|---|---|
|
||||
| `mode` | `SpriteMode` | Нет | Режим генерации; можно передать через CLI/API |
|
||||
| `source` | `local \| remote` | `local` | Исходные SVG либо готовый server manifest |
|
||||
| `name` | `string` | Выводится из каталога | Имя спрайта; в modes с компонентом также задаёт имя компонента и публичных типов |
|
||||
| `description` | `string` | Нет | Описание для типов и debug manifest |
|
||||
| `input` | `string \| string[]` | `./icons` | Папки, SVG-файлы и glob-паттерны относительно папки конфига |
|
||||
| `input` | `SpriteInput \| SpriteInput[]` | `./icons` | Локальные SVG sources, server HTTP descriptors либо один remote manifest в зависимости от mode и source |
|
||||
| `transform` | `TransformOptions` | Все включены | Настройки подготовки SVG |
|
||||
| `generatedNotice` | `boolean` | `true` | Полное или короткое предупреждение в generated-файлах |
|
||||
|
||||
При `source: 'remote'` поле `input` содержит один local path или HTTP(S) URL
|
||||
manifest, созданного `standalone@server`. Remote consumer config может содержать
|
||||
только `mode`, `source` и `input`: name, description, transforms и generated notice
|
||||
проверяются и наследуются из server manifest. До codegen генератор скачивает profile,
|
||||
необходимый exact consumer mode, и проверяет его SHA-256 и размер. Runtime-зависимости
|
||||
от server manifest нет.
|
||||
|
||||
### Имя спрайта
|
||||
|
||||
`name` записывается в kebab-case и должно начинаться с латинской буквы:
|
||||
@@ -176,6 +185,26 @@ file-manager → FileManagerIcon
|
||||
|
||||
Каждый включающий источник или паттерн должен найти хотя бы один SVG, иначе генерация завершается ошибкой. Повторяющиеся пути удаляются, а итоговый список файлов детерминированно сортируется. Разные SVG с одинаковым basename по-прежнему считаются конфликтом, потому что basename задаёт публичное имя иконки.
|
||||
|
||||
### Server SVG inputs
|
||||
|
||||
`standalone@server` принимает те же local strings и HTTP(S) descriptors в массиве
|
||||
`input`:
|
||||
|
||||
```ts
|
||||
{
|
||||
name: 'brand-logo',
|
||||
url: 'https://assets.example.com/brand-logo.svg',
|
||||
sha256: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
|
||||
}
|
||||
```
|
||||
|
||||
`name` становится публичным именем иконки. Необязательный `sha256` проверяется по
|
||||
скачанным байтам. URL credentials и активное SVG-содержимое, включая scripts,
|
||||
event handlers, `foreignObject` и doctype, запрещены. Один HTTP source ограничен
|
||||
2 MiB, все источники вместе — 25 MiB, timeout запроса равен 15 секундам. Local и
|
||||
HTTP entries используют единое пространство имён, поэтому duplicate icon names
|
||||
завершают генерацию с ошибкой.
|
||||
|
||||
## Generated-модуль
|
||||
|
||||
После генерации React- или Next.js-каталог спрайта выглядит так:
|
||||
@@ -225,6 +254,20 @@ runtime asset и deployment-neutral manifest data:
|
||||
generated Web Component без внешних runtime-зависимостей. Bare `standalone`
|
||||
намеренно не создаёт JavaScript-компонент.
|
||||
|
||||
`standalone@server` создаёт готовый к публикации release без JavaScript runtime и
|
||||
`.gitignore`:
|
||||
|
||||
```text
|
||||
.svg-sprite/
|
||||
├── sprite.<content-hash>.svg
|
||||
├── sprite-root-viewbox.<content-hash>.svg
|
||||
└── svg-sprite.manifest.json
|
||||
```
|
||||
|
||||
Manifest описывает оба compile profiles через relative `href`, полный SHA-256 и
|
||||
размер в байтах. Публикуйте весь каталог атомарно; consumer разрешает каждый profile
|
||||
относительно URL или local path manifest.
|
||||
|
||||
`.svg-sprite` полностью управляется генератором и при каждой генерации заменяется целиком. Любые добавленные в него файлы будут удалены. Пользовательские файлы размещайте рядом, например в корневом `index.ts`:
|
||||
|
||||
```ts
|
||||
|
||||
Reference in New Issue
Block a user