Что значит версия 1.0.0 — и почему проект ломается сам по себе

Вот история, которая случается с каждым. Проект неделю лежал нетронутым. Ты не менял ни строчки. Открываешь — не собирается. Никто тебя не взламывал: просто одна из библиотек обновилась, и твой проект послушно взял новую версию. Разрешение на это ты дал сам — одним символом, которого даже не заметил.
Чтобы понять, каким, нужно уметь читать три числа вида 1.0.0. Это язык версий, semver — и он проще, чем выглядит.
Три числа — три обещания
Semver (semantic versioning, «осмысленные версии») — договорённость о том, что значит каждое число в версии MAJOR.MINOR.PATCH, например 18.2.1:
- MAJOR (18) — «мы сломали совместимость». Что-то из старого поведения изменилось или исчезло. Обновляешься — будь готов чинить свой код.
- MINOR (2) — «добавили новое, старое не трогали». Новые функции, твой код должен работать как раньше.
- PATCH (1) — «починили баги». Ничего нового, просто исправления.
Ключевая мысль: версия — это не счётчик релизов, а обещание. 18.2.1 → 18.3.0 — «можно спокойно». 18.2.1 → 19.0.0 — «остановись и прочитай, что изменилось».
Значок ^, который ты не ставил
Открой package.json любого проекта — у зависимостей написано не 18.2.1, а ^18.2.1. Эту крышечку npm ставит по умолчанию при установке пакета.
^ означает «эта версия или новее — но в пределах текущего мажора». То есть ^18.2.1 разрешает и 18.2.5, и 18.9.0, но не 19.0.0. Есть и скромный собрат ~: он разрешает только патчи (~18.2.1 → до 18.2.9, но не 18.3.0).
Теперь понятна история из начала. Библиотека выпустила новый minor, твой ^ его разрешил — и при следующей установке зависимостей проект получил код, который ты не видел. По обещанию semver это безопасно. Но обещание держат люди, а люди ошибаются: иногда ломающее изменение уезжает в minor по недосмотру. Так проект «ломается сам».
Версии 0.x — зона без обещаний
Отдельное правило, о котором почти никто не знает: до 1.0.0 обещания не действуют. Версия 0.x — официальный сигнал «мы ещё экспериментируем, ломать можем в любом релизе».
npm об этом знает и осторожничает: для ^0.2.3 он не станет брать 0.3.0 — только патчи в пределах 0.2.x. Смешной вывод: у пакетов-нулёвок крышечка строже, чем у взрослых.
Поэтому библиотека с версией 0.9.14, которой пользуются миллионы, — не парадокс, а честность: авторы пока не готовы дать обещание совместимости.
Lock-файл — фотография, которая всех спасает
Рядом с package.json живёт файл package-lock.json (или pnpm-lock.yaml). Это точная фотография всех установленных версий — до последней цифры, включая зависимости зависимостей.
Пока lock-файл в проекте и закоммичен, npm install ставит ровно то, что на фотографии, — и «у меня работает, у тебя нет» случается гораздо реже. Удалил его «чтобы починить» — все ^ разморозились, и ты получил свежий набор версий со всеми сюрпризами. Кстати, это одна из классических причин, почему npm install падает у одного человека из всей команды.
Практический итог — три привычки:
- Lock-файл коммить всегда, руками не редактировать и не удалять.
- Патчи и миноры обновляй спокойно, мажоры — отдельным заходом: один пакет, прочитать changelog (список изменений), проверить проект.
- Увидел
beta,rcилиalphaв версии — это черновики релиза, новичку они не нужны.
Почему у популярной библиотеки версия 0.x годами?
Потому что 1.0.0 — это обязательство: после него любое ломающее изменение требует нового мажора. Авторы не спешат давать такое слово. Пользоваться можно — просто обновляйся внимательнее.
Большой номер мажора — значит много нового?
Не обязательно. Мажор говорит только «есть хотя бы одно ломающее изменение» — иногда оно одно-единственное. А бывает наоборот: огромный релиз с сотней фич выходит как minor, потому что ничего старого не сломал.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





