Версионирование

  • Обновления и помощь
  • 7 мин
  • кода: 1

Что обещает 3.x, как пакеты семейства связаны версиями и чего библиотека пока не обещает.

Ревизия 2026-10-27

На этой странице

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

С 1.0

Библиотека нумерует выпуски по Semantic Versioning, и с 1.0 публичная поверхность — компоненты, их подпути, токены и реестры — ломается только мажором. На 0.x было иначе: минорный выпуск мог сломать совместимость, и ломал. Версия 0.41.0 вынесла GrCodeBlock из ядра в @feugene/granularity-code, и подпуть @feugene/granularity/components/GrCodeBlock исчез:

diff
- import { GrCodeBlock } from '@feugene/granularity'
+ import { GrCodeBlock } from '@feugene/granularity-code/components/GrCodeBlock'

Причина названа в журнале изменений и она про 1.0: вынести что-то из замороженного ядра стоит мажора, поэтому переезды такого рода делались до заморозки, а не после. Первым мажором по этому правилу стала 2.0: темы и режимы поменяли конфиг сборки и API переключения. Вторым — 3.0: значения токенов компонентов переехали в темы, а themes в конфиге granum стал обязательным. Оба переезда описаны в миграции.

С мажора 1 ^ и ~ различаются. ^3.0.0 разворачивается в >=3.0.0 <4.0.0 и принимает новые миноры, ~3.0.0 — в >=3.0.0 <3.1.0. На нулевом мажоре — у @feugene/granularity-datasource 0.1.x и у peer @feugene/fint-i18n — ^ по-прежнему значит то же, что ~.

Каждый пакет версионируется сам

Общей версии у семейства нет, и это не недосмотр. У ядра и спутников разный цикл: ядро выпускает патч за патчем, спутник может неделями стоять на своей версии, @feugene/granularity-datasource и вовсе ещё на 0.x, а пакет токенов @feugene/granularity-tokens начал свою нумерацию с 1.0 вместе с ядром 2.0 и перешёл на 2.0 вместе с ядром 3.0. Лишний выпуск спутника ради выпуска ядра означал бы обновление, за которым не стоит ни одного изменения.

Из этого следует три вещи, и все три видны в репозитории:

  1. У каждого пакета свой журнал изменений. Общего журнала в корне нет намеренно — журналы на портале собраны из них.
  2. У каждого пакета свой тег. Ядро выпускается тегом vX.Y.Z, спутник — <имя-каталога>-vX.Y.Z, например granularity-charts-v2.0.0.
  3. Публикация идёт из тега. Пуш тега запускает публикацию в npm с --provenance: у пакета в npm есть прослеживаемое происхождение, и это проверяет ваш сканер, а не мы. Зеркало в GitHub Packages выходит под scope @efureev и без provenance.

Матрица совместимости

Спутник объявляет, с какой версией ядра и конвейера он работает, — не словами, а диапазоном в peerDependencies. Ваш менеджер пакетов прочитает его сам и о несовместимой паре скажет: npm — предупреждением, pnpm и yarn berry со строгими настройками — отказом установки. Здесь тот же диапазон в читаемом виде:

ПакетЯдро @feugene/granularityКонвейер @feugene/granumVue
@feugene/granularity-charts>=3.1.0 <4.0.0>=3.11.0 <4.0.0^3.5.0
@feugene/granularity-chrono>=3.5.0 <4.0.0>=3.10.0 <4.0.0^3.5.0
@feugene/granularity-code>=3.5.0 <4.0.0>=3.10.0 <4.0.0^3.5.0
@feugene/granularity-dashboard>=3.1.0 <4.0.0>=3.11.0 <4.0.0^3.5.0
@feugene/granularity-datasource——^3.5.0
@feugene/granularity-devtools>=2.4.0 <4.0.0>=3.8.0 <4.0.0^3.5.0
@feugene/granularity-editor>=3.5.0 <4.0.0>=3.10.0 <4.0.0^3.5.0
@feugene/granularity-forms-schema>=3.1.0 <4.0.0>=3.10.0 <4.0.0^3.5.0
@feugene/granularity-media>=3.1.0 <4.0.0>=3.10.0 <4.0.0^3.5.0
@feugene/granularity-test-kit—>=3.0.0 <4.0.0^3.5.0
@feugene/granularity-tokens—>=3.10.0 <4.0.0—
@feugene/unplugin-granularity>=1.0.0 <4.0.0——

В таблице — связь с ядром, конвейером и Vue. Остальные peer-зависимости — например, опциональные @feugene/fint-i18n >=0.9.0 <1.0.0 и @feugene/unplugin-granularity, @feugene/granularity-chrono у forms-schema, библиотеки редакторов и схем у своих спутников — смотрите в package.json пакета. У test-kit конвейер и Vue опциональны.

Прочерк означает, что пакет этой зависимости не объявляет вовсе: granularity-datasource не знает ни о ядре, ни о конвейере — он про данные, а не про разметку; test-kit работает с любым ядром, потому что проверяет CSS и DOM, а не импортирует компоненты; granularity-tokens — словарь токенов и темы, и зависит от него само ядро, а не наоборот.

Спутники с компонентами держат свои значения в теме — цвет, линии, шрифт решает тема, а не код пакета. Поэтому ядро 2.x им не подходит: каталог тем ядро приносит с 3.1, через пакет токенов, — у charts, dashboard, forms-schema и media диапазон ядра >=3.1.0 <4.0.0. chrono, code и editor рисуют поле общим листом рамки ядра и стоят на >=3.5.0 <4.0.0. Ядро 2.x осталось только у devtools (>=2.4.0), который читает состояние компонентов, а не рисует их, и у unplugin-granularity: он разрешает компоненты, не порождая ни одного правила, — >=1.0.0 <4.0.0.

Колонка конвейера живёт своим мажором: все пакеты собраны granum 3, а нижняя граница — механизм, на котором пакет стоит: значения компонентов у темы — granum 3.10, раздел темы для группы компонентов — 3.11. Смешивать их со спутником, собранным под ядро 1, нельзя: манифесты granum 2 и 3 несовместимы, а конфиг со списком themes, на который опирается документация, понимает только granum 3.8 и новее.

Таблица набрана руками, но сверяется с манифестами в CI портала: диапазон ядра или Vue, разошедшийся с package.json спутника, роняет прогон. Колонку конвейера гейт пока не сверяет. И сверка идёт с тем тегом, на который закреплён подмодуль библиотеки, а не с тем, что лежит в npm сию секунду. Источник истины — peerDependencies установленного пакета.

Требования к окружению

ЧтоВерсияОткуда
Node>=22engines во всех пакетах семейства
Vue^3.5.0peer-зависимость
Формат модулейтолько ESM"type": "module", CommonJS-сборки нет

Эти три строки — тоже часть совместимости, и меняются они по тем же правилам: поднять нижнюю границу Node — ломающее изменение, и с 1.0 оно приезжает только мажором.

Документация одной версии

Документация описывает одну версию — ту, на которую закреплён портал; сейчас это линия 3.x. Архива прежних версий и переключателя нет: страницы 0.x, 1.x и 2.x на портале не сохранены, а переезд с них описан в миграции.

Версия в шапке читается из манифеста установленного ядра при сборке и руками не пишется.

Чего библиотека пока не обещает

Раздел существует потому, что молчание здесь читается как обещание. Ни одного из перечисленного сегодня нет:

  • срок жизни версии. Получает ли линия 2.x исправления после выхода 3.0 и сколько живёт минор после следующего — не объявлено;
  • период депрекации. Подпуть может исчезнуть в том же выпуске, в котором появилась замена: так и вышло с GrCodeBlock;
  • бэкпорт исправлений безопасности в предыдущие миноры;
  • метаданные since и deprecated у компонентов. Страница компонента не говорит, в какой версии появился проп: этих данных в библиотеке пока нет, и портал не станет их выдумывать.

Что делать вместо этого:

  1. Закрепляйте минор, если нужна предсказуемость: ~3.2.0 вместо ^3.2.0 — см. выноску выше, — и проверьте, что в package.json стоит диапазон, а не latest.
  2. Читайте журнал пакета, который поднимаете. Не общий: у каждого свой, и ломающее изменение описано там с диффом.
  3. Поднимайте по одному. Спутник и ядро связаны диапазоном, а не общей версией: обновление ядра не требует обновления спутников, пока диапазон сходится.

Где смотреть изменения

Журналы изменений на портале собраны из журналов пакетов в репозитории библиотеки — по одному на пакет, с диффами и объяснениями. Это тот же текст, что в репозитории: портал его не пересказывает.