# Производительность

> Гранулярность — главное обещание продукта. Страница показывает, чем оно измеряется и как проверить его самому.

- Page: https://granularity.tech/ru/docs/performance
- Last reviewed: 2026-10-16

Обещание формулируется коротко: **бандл растёт от того, что вы используете, а не
от того, что есть в пакете**. Ниже — чем это обеспечено, сколько стоит на самом
деле и как померить у себя, не веря на слово.

## Две стороны, и они не коррелируют

Вес компонента складывается из кода и стилей, и эти величины живут отдельно:

| Компонент | CSS, прирост листа | JS, сам компонент |
|---|---:|---:|
| `GrCard` | 235 B | 2 779 B |
| `GrDialog` | 670 B | 9 989 B |
| `GrDataTable` | 2 911 B | 36 431 B |
| `GrSelect` | 3 037 B | 23 216 B |

Тяжёлый по коду компонент может почти ничего не добавить к листу, и наоборот.
Поэтому «вес компонента» одним числом не измеряется, а любая таблица с одной
колонкой врёт. Числа те же, что на главной: их снимает скрипт замера по ядру,
а не человек.

## Код: подпуть вместо бареля

```ts
// один компонент и его граф
import { GrButton } from '@feugene/granularity/components/GrButton'

// весь пакет — granum 2 отвергает такой импорт: ComponentRootImportError
import { GrButton } from '@feugene/granularity'
```

Верхняя строка — это и есть гранулярность. Вес подпути — gzip всего, что он
тянет из `dist`, вместе с вложенными компонентами, но без внешних пакетов и без
CSS. Самый лёгкий подпуть — обёртка `GrButtonGroup`: сама по себе она весит
1.5 kB, но без своих кнопок не используется — `GrButton` приходит в неё слотом
и импортируется своим подпутём. Самый тяжёлый — `GrDataTable`, 115.8 kB. Весь
пакет из корня — 655.4 kB.

:::callout{type="warning"}
**Складывать веса подпутей нельзя.** Общий чанк посчитан в каждой строке заново,
а платится один раз: сумма пяти самых тяжёлых строк даёт 487.1 kB, а вместе они
весят 251.9 kB. Набор считается объединением, а не суммой — и это верхняя
граница: бандлер приложения трясёт дерево дальше и минифицирует повторно.
:::

Полная таблица по каждому подпути генерируется из собранного `dist` на каждом
релизе — она лежит в пакете и на странице каждого компонента в
[каталоге](/ru/components).

## Стили: платите за выбранное

CSS не импортируется файлами — его собирает granum ровно для тех компонентов,
которые вы перечислили в `components`, и для их зависимостей. Что нужно каждому
компоненту — классы, собственный `styles.css`, токены, — записано в манифесте
пакета, и лист собирается по манифестам, а не по `node_modules`. Структура
расхода такая:

:::steps
1. **Первый компонент несёт фундамент** — токены, базовый слой, preflight, тему. Это разовая плата.
2. **Каждый следующий добавляет свои сотни байт** — от двух сотен у карточки до трёх килобайт у селекта.
3. **Вторая тема стоит около полутора килобайт**, а не вдвое: темы отличаются значениями ролей, а не правилами.
:::

Не перечислять `components` вовсе — рабочий вариант: тогда в лист приедут все
компоненты провайдера. Разница между «всё» и «один» на общем листе — примерно
вдвое, а не в сто раз, потому что фундамент один на всех. Гранулярность стилей
имеет смысл, но её эффект скромнее, чем у кода, и честно сказать об этом дешевле,
чем потом объясняться.

## Рантайм

- **Ноль runtime-зависимостей у ядра.** Единственная обязательная внешняя
  библиотека — `@floating-ui/dom`, и она объявлена peer-зависимостью
  приложения, чтобы не приехать второй копией.
- **CSS компонента приходит через манифест, а не через чанк.** JS-чанки пакета
  стилей не импортируют: granum берёт `styles.css` компонента из манифеста и
  кладёт его в слой `granum.components` — только для выбранных компонентов.
  Отдельного стилевого импорта нет, и это не удобство, а условие: иначе
  гранулярность ломалась бы на первом же забытом импорте.
- **Справочник токенов и тест-помощники — отдельные подпути** (`/tokens`,
  `/testing`), и барель ядра их не импортирует. Подсветки кода в ядре нет
  вовсе: она живёт в `@feugene/granularity-code/highlight`.

## Как померить у себя

:::steps
1. Соберите приложение с одним компонентом и снимите gzip эмитированного CSS и JS.
2. Добавьте второй компонент и снимите снова. Разница — его настоящая цена в вашем проекте.
3. Сравните с барелем: импорт из корня granum не пропустит, поэтому на время замера выключите guard (`js: { guard: 'off' }`) и повторите. Разница — то, от чего бережёт подпуть.
:::

Числа на этом сайте снимают скрипты, а не сборка приложения. В таблице в начале
страницы лист собирает granum по манифесту ядра без исходников приложения, а
код — esbuild по подпути компонента, где `vue`, `@floating-ui/dom` и
`@feugene/fint-i18n` вынесены наружу. Поэтому смотреть на них стоит как на
порядок величины: ваш результат зависит от версии бандлера, настроек
минификации и от того, что ещё лежит в графе.

## Что не ускорит ничего

- **`importStyle: true` у резолвера авто-импорта.** Ядру он не нужен: стили
  компонентов granum уже взял из манифестов, а подпутей
  `components/<Name>/styles.css` ядро не публикует — включённая опция сломала
  бы сборку.
- **Ручные импорты `styles/*.css`** поверх листа granum. Они добавят вес, а не
  уберут: токены, базу и темы granum уже положил в свои слои, а файл,
  импортированный вне слоёв, ещё и перебьёт их в каскаде.
- **Сужение `themes.names` до одной темы** ради экономии. Вторая тема стоит
  около полутора килобайт — это не то место, где стоит терять переключение.
