Семантическое версионирование (SemVer): как нумеровать версии
Основы3 минРедакция Innovialabs
Коротко
SemVer — это формат MAJOR.MINOR.PATCH, где MAJOR растёт при несовместимых изменениях, MINOR — при новых возможностях без поломок, PATCH — при исправлениях ошибок; lock-файл фиксирует точные версии зависимостей.
Коротко о SemVer
Семантическое версионирование — договорённость о том, что номер версии сообщает, насколько опасно обновление. Формат — MAJOR.MINOR.PATCH, например 2.5.1:
| Часть | Когда увеличивается | Что это значит для пользователя |
|---|---|---|
| MAJOR | несовместимые изменения публичного API | обновление может сломать ваш код |
| MINOR | новая функциональность с обратной совместимостью | можно обновлять, старое продолжит работать |
| PATCH | исправление ошибок без изменения API | безопасное обновление |
При увеличении старшей части младшие сбрасываются в ноль: 1.4.7 → 2.0.0, 1.4.7 → 1.5.0.
Ключевое понятие — публичный API. SemVer имеет смысл только тогда, когда явно определено, что считается «интерфейсом»: функции библиотеки, эндпоинты, формат конфигурации. Изменение внутреннего кода, который никто снаружи не вызывает, не ломает совместимость.
Особые случаи
- Версии
0.x.y— начальная разработка. По спецификации в этот период может меняться что угодно, стабильности API не обещается. 1.0.0— момент, когда вы объявляете публичный API стабильным.- Pre-release — суффикс через дефис:
2.0.0-alpha.1,2.0.0-beta.3,2.0.0-rc.1. Такая версия считается младше финальной2.0.0и не обещает стабильности. - Build metadata — суффикс через плюс:
1.0.0+20261010. На порядок версий не влияет.
Порядок pre-release версий: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-rc.1 < 1.0.0.
Диапазоны ^ и ~ в менеджерах пакетов
В package.json (и аналогах в других экосистемах) зависимость часто указывают не точной версией, а диапазоном:
| Запись | Что разрешено | Пример для 1.4.2 |
|---|---|---|
1.4.2 | только эта версия | 1.4.2 |
~1.4.2 | обновления PATCH | >=1.4.2 <1.5.0 |
^1.4.2 | обновления MINOR и PATCH | >=1.4.2 <2.0.0 |
* или latest | что угодно | не рекомендуется |
Важная деталь npm: для версий ниже 1.0.0 знак ^ ведёт себя осторожнее. ^0.3.1 разрешает только >=0.3.1 <0.4.0, потому что в нулевой мажорной версии MINOR фактически играет роль MAJOR.
Точные правила разбора диапазонов описаны в документации npm: semver ranges.
Lock-файлы: защита от «вчера работало»
Диапазон ^1.4.2 означает, что при новой установке вы можете получить 1.9.0. Если автор библиотеки случайно сломал совместимость в MINOR-версии, ваш проект упадёт без единого изменения в коде.
Lock-файл (package-lock.json, yarn.lock, pnpm-lock.yaml, poetry.lock, composer.lock) фиксирует точные версии всего дерева зависимостей, включая транзитивные. Что важно на практике:
- Коммитьте lock-файл в репозиторий для приложений.
- В CI используйте строгую установку:
npm ciвместоnpm install— она ставит ровно то, что в lock-файле, и падает, если он не совпадает сpackage.json. - Обновляйте зависимости осознанно: отдельной задачей, с прогоном тестов и чтением changelog для MAJOR-версий.
- Инструменты автоматических обновлений вроде Dependabot или Renovate создают отдельные pull request’ы — это удобно, если у проекта есть тесты.
Как версионировать свой проект
- Определите, что является публичным API, и опишите это в документации.
- Ведите CHANGELOG: что добавлено, исправлено, что ломает совместимость.
- Удаляйте функциональность в два шага: сначала пометка deprecated в MINOR-версии, удаление — в следующей MAJOR.
- Не бойтесь выпускать MAJOR-версии: честный номер лучше, чем «тихая» поломка в PATCH.
- Для сайтов и внутренних приложений без внешних потребителей строгий SemVer не обязателен — часто хватает даты или номера сборки.