React

Большинство компонентов версионируются как часть проекта (например, component-library), что противоречит концепции создания модульных UI-приложений. Например, чтобы использовать слайдер-компонент, нужно внедрить в приложение полную библиотеку с единой версией, которой должен соответствовать каждый компонент.

Версионирование отдельных компонентов с использованием SemVer обеспечивает детальный контроль над составом UI-приложений. Разработчики могут использовать общие компоненты, а также получают возможность обновлять части пользовательского интерфейса без конфликтов, сохраняя при этом независимость команды.

Недостатки библиотек с единой версией

Создание единой версии для библиотеки компонентов является распространенной практикой.

library 1.0.0
├─ visual style
└─ components
   ├─ button
   ├─ button group
   ├─ card
   ├─ checkbox
   ├─ radio button
   └─ ...

Большинство библиотек представляют собой единый версионный пакет:

npm install @material-ui/core

Эта практика затрудняет внедрение компонентов, вынуждая разработчиков связывать свою разработку с библиотекой, согласовывать все версии и обновлять все компоненты на каждой из них.

Есть лучший вариант: версионирование и распределение отдельных компонентов по правилам SemVer. Они также используются в инструментах проектирования и предоставляют возможность согласовывать дизайн и код каждого компонента к единой версии.

library
├─ visual style
└─ components
   ├─ button       5.3.1
   ├─ button group 2.1.0
   ├─ card         3.7.6
   ├─ checkbox     3.1.0
   ├─ radio button 1.1.0
   └─ ...

Версионирование компонентов предоставляет множество преимуществ как для разработчиков, так и для пользователей: первые могут непрерывно передавать обновления для определенных компонентов, а вторые получают эти обновления без возникновения конфликтов.

Преимущества версионирования компонентов

Обновления

Пользователи могут получать обновления только тех компонентов, которые они используют. Правила SemVer отлично подходят для связи различных обновлений по старшим, младшим и патч-версиям.

Такие инструменты, как Bit, упрощают этот процесс как для разработчиков, так и для пользователей, предоставляя такие функции, как автоматическое создание тегов для зависимых компонентов при внесении изменений.

Избежание избыточных конфликтов зависимостей

Разработка внутренних компонентов и одновременное добавление сторонней библиотеки создают конфликты версий зависимостей.

Например, в приложении находится внутренний компонент «Scroller» с зависимостью «Scroll-JS» в версии 3.0.1. Сторонняя библиотека добавляет в приложение компонент «Button». Однако она также содержит компонент «Scroller», зависимый от «Scroll-JS» в версии 2.0.2. В данном случае могут возникнуть конфликты.

Избыточный конфликт версий зависимостей

Тем не менее, если приложение принимает из библиотеки только компонент «Button», то конфликт полностью устраняется.

Избыточный конфликт устранен!

Непрерывные релизы, исправления и откаты

Библиотеки компонентов с единой версией не позволяют распространителю выпускать постепенные обновления для каждого компонента. Например, новая старшая версия «Slider» не может быть выпущена до следующей старшей версии библиотеки. То же самое касается младших и патч-версий, которые обновляют версию в соответствии с библиотекой.

Версионирование отдельных компонентов предоставляет возможность непрерывного релиза обновлений и безопасного выполнения отката или внесения исправлений. Таким образом, версию «Slider» можно повысить с 1.0.0 до 1.0.1, не дожидаясь следующего релиза библиотеки.

Смешение и соответствие UI-композиции

Компоненты SemVer можно использовать для внедрения набора общих компонентов и объединения их со специальными версиями.

Например, можно безконфликтно внедрить набор общих компонентов с версией 1.0.0 и обновить только «Slider» с патчем до версии 1.0.1. В крайних случаях возможно даже представить различные версии компонента на одной странице.

С помощью bit import это можно выполнить локально прямо в приложении. Поскольку HTML-разметка, стиль и сценарий инкапсулированы в компоненте, он не будет конфликтовать с другими типами компонентов.

Сохранение независимости команды

Когда команда принимает библиотеку с единой версией, она связывает разработку своего приложения с разработкой библиотеки, что предполагает управление roadmap’ом продукта и свободу предоставления обновлений.

Версионирование компонентов «узаконивает» внедрение и модификацию компонентов, а такие инструменты, как Bit, «легализуют» разработку общих компонентов. С помощью команды bit import разработчики, использующие общие компоненты, могут изменять и обновлять любой из них, а также смешивать версии и добавлять собственные компоненты и версии в коллективный пул.

Производительность, стабильность и скорость разработки

Версионирование отдельных компонентов ускоряет разработку и повышает производительность созданного приложения.

Производительность. При добавлении и использовании лишь необходимых компонентов уменьшается размер пакета приложения. В результате браузер анализирует меньшее количество кода, что сокращает время выполнения.

Стабильность. Компоненты SemVer повышают стабильность благодаря безопасному внедрению постепенных обновлений в определенные UI. При обновлении отдельных компонентов также упрощается использование модульных тестов. Bit тестирует и собирает каждую версию в отдельности, прежде чем внедрить ее в приложение.

Скорость разработки. Использование общих компонентов повышает скорость работы команды. При необходимости обновление можно как запросить, так и выполнить самостоятельно (т.е. bit import). В результате экономится время на разработку новых функций и на обслуживание текущей базы кода.

Распределение SemVer для каждого компонента с использованием Bit

Bit — это инструмент, выполняющий тегирование различных компонентов на основе SemVer внутри одного проекта (библиотеки или приложения).

С помощью команды bit add Bit отслеживает компоненты в репозитории, анализирует каждый из них и выполняет поиск всех его файлов и зависимостей. Он автоматизирует процесс упаковки компонента, генерирует файл package.json и изолирует его встроенную/тестовую среду. В результате каждый компонент может быть версионирован, собран, протестирован и экспортирован по отдельности.

Команда bit tag тегирует компонент с помощью SemVer, а затем Bit подсказывает, какие компоненты также необходимо обновить, и автоматически тегирует их.

Версионированные компоненты можно экспортировать и распространять между командами и проектами. После обновления до новой версии компонент может независимо обновляться различными приложениями по правилам SemVer.

Bit также помогает сохранить независимость каждой команды, предоставляя возможность импортировать (bit import) общие компоненты в собственный проект.

Пример: тегирование компонентов в проекте

В этом примере показан компонент hello/world. Предположим, что он уже изолирован и добавлен в Bit (с помощью bit add). В таком случае ему уже предоставлены независимые конфигурации сборки и тестирования (Bit также автоматизирует этот процесс). С этого момента компонент становится отдельной единицей, находящейся внутри проекта.

При запуске bit status получаем следующий вывод:

$ bit status
new components
    > hello/world... ok

Чтобы тегировать компонент hello/world, используем bit tag:

$ bit tag hello/world
1 components tagged | 1 added, 0 changed, 0 auto-tagged
added components:  hello/[email protected]

Вы также можете тегировать все новые или модифицированные компоненты в области видимости с помощью --all:

$ bit status
new components
    > hello/world... ok
    > ui/button... ok
modified components
    > string/pad-left... ok

$ bit tag --all
3 components tagged | 2 added, 1 changed, 0 auto-tagged
added components:  hello/[email protected], ui/[email protected]
changed components: string/[email protected]

С помощью опции --scope можно тегировать все компоненты, находящиеся в локальной области видимости. Bit согласовывает все компоненты по указанному номеру версии:

bit tag --scope 1.0.1 # все компоненты в локальной области видимости установлены на версии 1.0.1

Bit может устанавливать определенную версию при тегировании компонента:

$ bit tag hello/world 1.0.0
1 components tagged | 1 added, 0 changed, 0 auto-tagged
added components:  hello/[email protected]

Bit также может тегировать все компоненты с помощью указанного инкремента SemVer. Bit поддерживает такие инкременты, как patchminor и major:

bit tag --all --major          # Инкрементирование всех измененных и новых компонентов с помощью старшей версии.
bit tag --all --minor          # Инкрементирование всех измененных и новых компонентов с помощью младшей версии.
bit tag --scope --patch  # Инкрементирование всех компонентов с помощью патч-версии.
bit tag --scope --patch  # Инкрементирование всех компонентов в рабочем пространстве с помощью патч-версии.

После тегирования компоненты можно экспортировать с помощью bit export в удаленную коллекцию.

Пример: обновление и автоматическое тегирование зависимостей

Bit управляет зависимостями благодаря сохранению полного графа зависимостей компонентов. После тегирования Bit также помечает другие компоненты, находящиеся в локальной области видимости и зависящие от него.

Зависимые компоненты всегда помечаются patch версией независимо от основного инкремента компонента.

Допустим, у нас есть 2 компонента: navbar и main-menu. navbar импортирует компонент mainmenu следующим образом:

import MainMenu from '../main-menu/main-menu';

Отслеживаем компоненты в bit с помощью команды bit addbit status отображает добавленные компоненты:

$bit status
new components
(use "bit tag --all [version]" to lock a version with all your changes)

     > main-menu ... ok
     > navbar ... ok

Тегируем оба компонента до версии 0.0.1:

$bit tag --all
2 component(s) tagged
(use "bit export [collection]" to push these components to a remote")
(use "bit untag" to unstage versions)

new components
(first version for components)
     > [email protected]
     > [email protected]

Снова запускаем bit status, который теперь отображает тегированные компоненты:

$bit status
staged components
(use "bit export <remote_scope> to push these components to a remote scope")

     > main-menu. versions: 0.0.1 ... ok
     > navbar. versions: 0.0.1 ... ok

Теперь внесем некоторые изменения в код main-menu, который является зависимостью navbar, и снова запускаем bit status:

$bit status
modified components
(use "bit tag --all [version]" to lock a version with all your changes)
(use "bit diff" to compare changes)

     > main-menu ... ok

staged components
(use "bit export <remote_scope> to push these components to a remote scope")

     > main-menu. versions: 0.0.1 ... ok
     > navbar. versions: 0.0.1 ... ok

components pending to be tagged automatically (when their dependencies are tagged)
     > navbar ... ok

Мы видим, что main-menu изменено, а navbar также тегируется, поскольку его зависимость была изменена.

Теперь тегируем main-menu. В результате мы видим, что navbar также тегирован:

$bit tag main-menu
2 component(s) tagged
(use "bit export [collection]" to push these components to a remote")
(use "bit untag" to unstage versions)

changed components
(components that got a version bump)
     > [email protected]
       auto-tagged dependents: [email protected]

После этого все тегированные компоненты, включая зависимости, переходят в состояние staged. Для проверки можно запустить bit status.

Заключение

Версионирование отдельных компонентов — это важнейший шаг на пути к сохранению независимости команды, безопасному созданию и развертыванию частей приложения, а также совместному использованию и синхронизации компонентов в различных приложениях.

Читайте также:


Перевод статьи Jonathan Saring: The Case for Versioning Independent UI Components