Версионирование
Что обещает 1.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: вынести что-то из замороженного ядра стоит мажора, поэтому переезды такого рода делались до заморозки, а не после.
На мажоре 1 ^ и ~ различаются. ^1.0.0 разворачивается в >=1.0.0 <2.0.0
и принимает новые миноры, ~1.0.0 — в >=1.0.0 <1.1.0. На нулевом мажоре — у
@feugene/granularity-datasource 0.1.x и у peer @feugene/fint-i18n — ^
по-прежнему значит то же, что ~.
Каждый пакет версионируется сам
Общей версии у семейства нет, и это не недосмотр. У ядра и спутников разный
цикл: ядро выпускает патч за патчем, спутник может неделями стоять на своей
версии, а @feugene/granularity-datasource и вовсе ещё на 0.x. Лишний выпуск
спутника ради выпуска ядра означал бы обновление, за которым не стоит ни одного
изменения.
Из этого следует три вещи, и все три видны в репозитории:
- У каждого пакета свой журнал изменений. Общего журнала в корне нет намеренно — журналы на портале собраны из них.
- У каждого пакета свой тег. Ядро выпускается тегом
vX.Y.Z, спутник —<имя-каталога>-vX.Y.Z, напримерgranularity-charts-v1.0.4. - Публикация идёт из тега. Пуш тега запускает публикацию в npm с
--provenance: у пакета в npm есть прослеживаемое происхождение, и это проверяет ваш сканер, а не мы. Зеркало в GitHub Packages выходит под scope@efureevи без provenance.
Матрица совместимости
Спутник объявляет, с какой версией ядра и конвейера он работает, — не словами, а
диапазоном в peerDependencies. Ваш менеджер пакетов прочитает его сам и о
несовместимой паре скажет: npm — предупреждением, pnpm и yarn berry со строгими
настройками — отказом установки. Здесь тот же диапазон в читаемом виде:
| Пакет | Ядро @feugene/granularity | Конвейер @feugene/granum | Vue |
|---|---|---|---|
@feugene/granularity-charts | >=1.0.0 <2.0.0 | >=2.0.0 <3.0.0 | ^3.5.0 |
@feugene/granularity-chrono | >=1.0.0 <2.0.0 | >=2.0.0 <3.0.0 | ^3.5.0 |
@feugene/granularity-code | >=1.0.0 <2.0.0 | >=2.0.0 <3.0.0 | ^3.5.0 |
@feugene/granularity-dashboard | >=1.0.0 <2.0.0 | >=2.0.0 <3.0.0 | ^3.5.0 |
@feugene/granularity-datasource | — | — | ^3.5.0 |
@feugene/granularity-devtools | >=1.0.0 <2.0.0 | — | ^3.5.0 |
@feugene/granularity-editor | >=1.0.0 <2.0.0 | >=2.0.0 <3.0.0 | ^3.5.0 |
@feugene/granularity-forms-schema | >=1.0.0 <2.0.0 | >=2.0.0 <3.0.0 | ^3.5.0 |
@feugene/granularity-media | >=1.0.0 <2.0.0 | >=2.0.0 <3.0.0 | ^3.5.0 |
@feugene/granularity-test-kit | — | >=2.0.0 <3.0.0 | ^3.5.0 |
@feugene/unplugin-granularity | >=1.0.0 <2.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,
а не импортирует компоненты; unplugin-granularity разрешает компоненты, не
порождая ни одного правила.
Семейство пришло к 1.0 вместе, и диапазоны об этом и говорят: нижняя граница
>=1.0.0, верхняя — <2.0.0. Раньше граница была <1.0.0 и означала «дальше
границы обещаний нет». 1.0 контракт переопределила, и диапазоны переписаны
вместе с ним — ровно как и было обещано.
Колонка конвейера живёт своим мажором: с выпуска 1.1.0 спутники собраны granum 2
и объявляют >=2.0.0 <3.0.0 — granum 1 рецепты темизации и запрет корневого
импорта, на которые опирается документация, не выполняет.
Таблица набрана руками, но сверяется с манифестами в CI портала: диапазон ядра
или Vue, разошедшийся с package.json спутника, роняет прогон. Колонку
конвейера гейт пока не сверяет. И сверка идёт с тем тегом, на который закреплён
подмодуль библиотеки, а не с тем, что лежит в npm сию секунду. Источник истины —
peerDependencies установленного пакета.
Требования к окружению
| Что | Версия | Откуда |
|---|---|---|
| Node | >=22 | engines во всех пакетах семейства |
| Vue | ^3.5.0 | peer-зависимость |
| Формат модулей | только ESM | "type": "module", CommonJS-сборки нет |
Эти три строки — тоже часть совместимости, и меняются они по тем же правилам: поднять нижнюю границу Node — ломающее изменение, и с 1.0 оно приезжает только мажором.
Документация одной версии
Документация описывает одну версию — ту, на которую закреплён портал; сейчас
это линия 1.x. Архива /v0/ и переключателя версий нет: страницы 0.x на портале
не сохранены, а переезд с них описан в миграции.
Версия в шапке читается из манифеста установленного ядра при сборке и руками не пишется.
Чего библиотека пока не обещает
Раздел существует потому, что молчание здесь читается как обещание. Ни одного из перечисленного сегодня нет:
- срок жизни версии. Сколько линия 1.x будет получать исправления после выхода 2.0 и сколько живёт минор после следующего — не объявлено;
- период депрекации. Подпуть может исчезнуть в том же выпуске, в котором
появилась замена: так и вышло с
GrCodeBlock; - бэкпорт исправлений безопасности в предыдущие миноры;
- метаданные
sinceиdeprecatedу компонентов. Страница компонента не говорит, в какой версии появился проп: этих данных в библиотеке пока нет, и портал не станет их выдумывать.
Что делать вместо этого:
- Закрепляйте минор, если нужна предсказуемость:
~1.0.0вместо^1.0.0— см. выноску выше, — и проверьте, что вpackage.jsonстоит диапазон, а неlatest. - Читайте журнал пакета, который поднимаете. Не общий: у каждого свой, и ломающее изменение описано там с диффом.
- Поднимайте по одному. Спутник и ядро связаны диапазоном, а не общей версией: обновление ядра не требует обновления спутников, пока диапазон сходится.
Где смотреть изменения
Журналы изменений на портале собраны из журналов пакетов в репозитории библиотеки — по одному на пакет, с диффами и объяснениями. Это тот же текст, что в репозитории: портал его не пересказывает.