Миграция
Переезды между мажорами: что сломали переходы на 1.0, 2.0 и 3.0 и как их пройти.
Мажорных переходов у библиотеки три. С 2.x на 3.0 значения компонентов переехали в темы: имена токенов — контракт ядра, значения даёт тема. С 1.x на 2.0 пришли темы и режимы: тема стала данными пакета токенов, светлый и тёмный — её режимами, сборка — granum 3. С 0.x на 1.0 сменился конвейер, которым приложение собирает CSS. Все три переезда ломающие, хотя ни один импорт компонента в них не меняется.
С 2.x на 3.0
Компоненты, их пропсы и внешний вид «Сланца» не меняются: значения, которые видят компоненты в каждом режиме и острове, совпадают с 2.x. Меняется то, где эти значения живут и кто отвечает за их полноту.
| Было в 2.x | Стало в 3.0 |
|---|---|
peer @feugene/granum >=3.8.0 <4.0.0 | >=3.10.0 <4.0.0; пакет токенов @feugene/granularity-tokens — мажор 2 |
конфиг granum без themes собирал тему каталога по умолчанию | themes обязателен: основную тему выбирает приложение, без него — ошибка granum со списком тем каталога |
GR_DEFAULT_THEME_ID | GR_BASE_THEME_ID — базовая тема пакета, а не основная тема чьей-то сборки |
| значения токенов компонентов — у самих компонентов | значения — в теме, разделом components/@feugene/granularity/<GrX>/ |
| токен темы компонент читал с запасным значением | без запасного: нехватку называет granum doctor (theme-incomplete) |
--gr-button-neutral-bg — хук, его задавала тема | токен темы; хук — ручка приложения, и в данных темы он — находка theme-token-foreign |
theme.json с режимами массивом и componentDefaults в корне | режимы — объектом, пропсы по умолчанию — в extensions.granularity.componentDefaults, файл режима — плоские значения |
Свои значения поверх темы приложение задаёт как прежде — modes.tokenOverrides
записи темы или своим CSS; хук остаётся ручкой приложения поверх токена темы.
Молча ломается одно — своя тема без extends, которая опиралась на запасные
значения компонентов. Ошибки сборки нет: компонент просто не получает токен, а
granum doctor называет его поимённо. Значения дописываются в раздел
components темы, либо тема наследует тему каталога; начать с копии удобно
командой gr-theme-copy slate <id>. Тема с extends: 'slate' работает как прежде
и теперь получает от «Сланца» и значения компонентов.
Спутники charts и media перешли на ядро 3 мажорами 3.0: их значения тоже
живут в теме, и диапазон ядра у них — >=3.1.0 <4.0.0. chrono, code,
dashboard, editor и forms-schema своих значений у темы не держат и работают
с обоими мажорами ядра. Полная карта переезда — в
документации библиотеки.
С 1.x на 2.0
Компоненты, их пропсы и внешний вид «Сланца» не меняются: значения токенов совпадают с 1.x, кроме двух исправленных дефектов тёмного острова — они описаны в журнале изменений. Меняется то, как тема попадает в сборку и как переключается режим.
| Было в 1.x | Стало в 2.0 |
|---|---|
peer @feugene/granum мажора 1 или 2 | >=3.0.0 <4.0.0, у выпусков с темами сборки — >=3.8.0 <4.0.0; движок @feugene/granum-engine-wind — тоже мажор 3 |
themes: { names: ['light', 'dark'] } | themes: [{ theme: 'slate', modes: ['light', 'dark'] }] — список тем сборки; объект themes падает InvalidConfigError |
themes.define, themes.tokenOverrides | modes.define, modes.tokenOverrides в записи темы |
data-theme="dark" на корне | пара data-theme="slate-dark"; классов .light и .dark нет |
[data-theme='dark'] .x в своём CSS | [data-theme$='-dark'] .x или пара целиком; dark: в утилитах работает без правок |
useTheme().theme — имя режима | theme — текущая тема сборки; режим — mode |
setTheme('dark'), toggleTheme() | setMode('dark'), toggleMode(); setTheme(id) переключает тему сборки |
тип ThemeName | GrModeName, GrThemeId |
<GrConfigProvider theme="dark"> | <GrConfigProvider mode="dark">; theme — остров другой темы сборки |
@feugene/granularity/theme: extendTheme, createTheme | @feugene/granularity-tokens/theme: extendMode, createMode, defineTheme |
@feugene/granularity/theme/apply | @feugene/granularity-tokens/theme/apply |
grThemeTokens из @feugene/granularity/tokens | grRoleTokens из @feugene/granularity-tokens |
styles/tokens.css, styles/themes/light.css и dark.css | themes/slate.css — оба режима одной темы |
Манифест режимов отдают один раз, там, где создаётся состояние:
initThemeEarly({ manifest }) или app.use(granularityThemePlugin, { manifest })
с manifest из virtual:granum/themes. Ключ хранилища прежний — gr-theme, и у
основной темы в нём по-прежнему имя режима: выбор пользователя переживает обновление.
Пакет токенов отдельно ставить не нужно — он приезжает зависимостью ядра.
Молча ломается одно — атрибут и селекторы с именем режима вместо пары.
data-theme="dark", поставленный руками, и свой CSS под [data-theme='dark'] не
дают ни ошибки, ни предупреждения: компоненты просто остаются в режиме по
умолчанию. theme="dark" у GrConfigProvider dev-сборка хотя бы подсветит
предупреждением.
Первые выпуски 2.x писали тему и режимы отдельными ключами — theme: 'slate' и
modes: { names: [...] }. С granum 3.8 это запись списка themes, а previews и
css.previews стали дополнительными темами со своими листами. Старые ключи granum
отвергает ошибкой конфига с подсказкой, куда переехало значение.
Спутники перешли на ядро 2 своими мажорами 2.x в тот же день: смешивать ядро 2 со спутником, собранным под ядро 1, нельзя — манифесты granum 2 и 3 несовместимы. Полная карта переезда — в документации библиотеки, ключи конфига granum — в его руководстве (ru, en).
С 0.x на 1.0
| Было в 0.x | Стало в 1.0 |
|---|---|
peer @feugene/unocss-preset-granular | peer @feugene/granum >=1.0.0 <2.0.0 и движок @feugene/granum-engine-wind |
uno.config.ts | granum.config.ts; движок передаётся инстансом — engine: windEngine() |
| CSS склеивался по порядку подключения | CSS приезжает модулем virtual:granum.css пятью слоями granum.* |
| сброс браузерных стилей — обычным CSS | сброс — в слое: @import '…' layer(reset);, иначе он перебьёт библиотеку |
defineGranularComponent, defineGranularProvider | defineGranumComponent, defineGranumProvider из @feugene/granum/contract — для авторов провайдеров |
Спутники, которые зависят от ядра, перешли на 1.0 в тот же день: их диапазон
ядра теперь >=1.0.0 <2.0.0, и с ядром 0.x он не сходится. Поэтому ядро и
спутники обновляются вместе. Пошаговое руководство — в документации granum
(ru,
en).
Ломающие правки внутри линии 0.x — в журнале изменений.
Что появится здесь к следующему мажору
- Карта изменений API — что переименовано, что удалено, что поменяло значение по умолчанию. Таблицей, а не прозой: по прозе не сделать поиск по имени пропа.
- Codemod. Переименования выполняются скриптом, а не руками: он живёт в репозитории рядом с миграцией и запускается одной командой.
- Что ломается молча. Отдельный раздел под изменения, которые не дают ни ошибки сборки, ни предупреждения, — сдвиг значения по умолчанию, смена порядка разрешения, другой ARIA-контракт. Это самая дорогая часть переезда и самая короткая в чужих гайдах. Один такой случай известен уже по 1.0 — сброс вне слоя, см. типовые поломки.
- Порядок действий для приложения, которое обновляется не сразу: что можно ставить рядом, что конфликтует, где проходит граница совместимости.
- Оценка трудоёмкости по размеру приложения — чтобы решение «переезжать сейчас или в следующем квартале» принималось по числу, а не по настроению.
Версии документации
Документация одна и описывает линию 3.x; архива 0.x, 1.x и 2.x на портале нет. Версия в шапке читается из манифеста установленного ядра на сборке и руками не пишется — она совпадает с тем, на чём собран портал.
Подробности политики версий — на странице версионирования.
Переход с другой библиотеки — это не миграция в этом смысле. Карты соответствия компонентов для него готовятся на отдельной странице — «Переход с другой библиотеки».