Версионирование
Что обещает 3.x, как пакеты семейства связаны версиями и чего библиотека пока не обещает.
Вопрос внедренца звучит не «какая сейчас версия», а «сколько эта версия проживёт». Честный ответ на сегодня: окно поддержки не объявлено. Ниже — что вместо него есть, что из этого проверяемо и что делать, пока обещания нет.
С 1.0
Библиотека нумерует выпуски по Semantic Versioning, и с
1.0 публичная поверхность — компоненты, их подпути, токены и реестры —
ломается только мажором. На 0.x было иначе: минорный выпуск мог сломать
совместимость, и ломал. Версия 0.41.0 вынесла GrCodeBlock из ядра в
@feugene/granularity-code, и подпуть @feugene/granularity/components/GrCodeBlock
исчез:
- 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. Лишний выпуск
спутника ради выпуска ядра означал бы обновление, за которым не стоит ни одного
изменения.
Из этого следует три вещи, и все три видны в репозитории:
- У каждого пакета свой журнал изменений. Общего журнала в корне нет намеренно — журналы на портале собраны из них.
- У каждого пакета свой тег. Ядро выпускается тегом
vX.Y.Z, спутник —<имя-каталога>-vX.Y.Z, напримерgranularity-charts-v2.0.0. - Публикация идёт из тега. Пуш тега запускает публикацию в npm с
--provenance: у пакета в npm есть прослеживаемое происхождение, и это проверяет ваш сканер, а не мы. Зеркало в GitHub Packages выходит под scope@efureevи без provenance.
Матрица совместимости
Спутник объявляет, с какой версией ядра и конвейера он работает, — не словами, а
диапазоном в peerDependencies. Ваш менеджер пакетов прочитает его сам и о
несовместимой паре скажет: npm — предупреждением, pnpm и yarn berry со строгими
настройками — отказом установки. Здесь тот же диапазон в читаемом виде:
| Пакет | Ядро @feugene/granularity | Конвейер @feugene/granum | Vue |
|---|---|---|---|
@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 | >=22 | engines во всех пакетах семейства |
| Vue | ^3.5.0 | peer-зависимость |
| Формат модулей | только ESM | "type": "module", CommonJS-сборки нет |
Эти три строки — тоже часть совместимости, и меняются они по тем же правилам: поднять нижнюю границу Node — ломающее изменение, и с 1.0 оно приезжает только мажором.
Документация одной версии
Документация описывает одну версию — ту, на которую закреплён портал; сейчас это линия 3.x. Архива прежних версий и переключателя нет: страницы 0.x, 1.x и 2.x на портале не сохранены, а переезд с них описан в миграции.
Версия в шапке читается из манифеста установленного ядра при сборке и руками не пишется.
Чего библиотека пока не обещает
Раздел существует потому, что молчание здесь читается как обещание. Ни одного из перечисленного сегодня нет:
- срок жизни версии. Получает ли линия 2.x исправления после выхода 3.0 и сколько живёт минор после следующего — не объявлено;
- период депрекации. Подпуть может исчезнуть в том же выпуске, в котором
появилась замена: так и вышло с
GrCodeBlock; - бэкпорт исправлений безопасности в предыдущие миноры;
- метаданные
sinceиdeprecatedу компонентов. Страница компонента не говорит, в какой версии появился проп: этих данных в библиотеке пока нет, и портал не станет их выдумывать.
Что делать вместо этого:
- Закрепляйте минор, если нужна предсказуемость:
~3.2.0вместо^3.2.0— см. выноску выше, — и проверьте, что вpackage.jsonстоит диапазон, а неlatest. - Читайте журнал пакета, который поднимаете. Не общий: у каждого свой, и ломающее изменение описано там с диффом.
- Поднимайте по одному. Спутник и ядро связаны диапазоном, а не общей версией: обновление ядра не требует обновления спутников, пока диапазон сходится.
Где смотреть изменения
Журналы изменений на портале собраны из журналов пакетов в репозитории библиотеки — по одному на пакет, с диффами и объяснениями. Это тот же текст, что в репозитории: портал его не пересказывает.