Lockfile — описанное дерево зависимостей проекта с конкретными версиями каждого пакета: что у тебя установлено, какой версии, чего, что от чего зависит. Нужен, чтобы гарантировать одинаковое состояние и работу проекта на разных устройствах. Lockfile генерируется yarn’ом, например во время выполнения команды yarn install. Пакетные менеджеры npm и pnpm делают то же самое, только файлы называются по-разному. В этой статье будем рассматривать все на примере yarn и генерируемого им lockfile файла — yarn.lock. Выглядит yarn.lock вот так: В lockfile содержится набор информации: version — фактически установленная версия пакета; resolved — путь для скачивания этой версии пакета; integrity — SHA хэш нужен для сравнения содержимого библиотеки (так yarn может проверить, было ли изменено содержимое файлов пакета); dependencies — зависимости, которые необходимы для работы пакета is-odd (встретятся в lockfile и node_modules, даже если их нет в проекте напрямую). Сами зависимости указаны в package.json, в: dependencies — зависимости, необходимые для работы приложения в проде; devDependencies — зависимости, которые нужны для разработки и тестирования (не попадут в прод); peerDependencies — зависимости, необходимые для работы приложения, но не устанавливаемые напрямую в пакете (обычно используют разработчики библиотек). Команда yarn install запустит установку dependencies и devDependencies, ориентируясь на версии пакетов, указанные в yarn.lock. Для корректной работы библиотеки с peerDependencies нужно «продублировать» peer зависимости в своем package.json. Если yarn.lock нет, то версии установятся согласно указанным в package.json.  Важное примечание. Не всегда! В ходе оптимизаций пакетный менеджер может выбрать и другую версию (так yarn пытается оптимизировать зависимости). Поэтому стоит использовать resolutions, peerDependencies, указывать диапазоны версий и др. инструменты. «Лайфхак»: внутри node_modules появится файл .yarn-integrity, который описывает текущее состояние папки node_modules. Для больших проектов вместо rm -rf node_modules && yarn install можно использовать просто rm -rf node_modules/.yarn-integrity && yarn install. Так yarn не будет скачивать уже имеющиеся пакеты, но построит дерево заново, и переустановка модулей произойдет в разы быстрее. Семантическое версионирование — это система, которая помогает справиться с хаосом зависимостей (dependency hell) и версионным несоответствием. Семантическое версионирование — набор правил и требований установки версий. Общие правила для установки версии (их больше, это основные): Учитывая номер версии МАЖОРНАЯ.МИНОРНАЯ.ПАТЧ, следует увеличивать: МАЖОРНУЮ версию, когда сделаны обратно несовместимые изменения API.МИНОРНУЮ версию, когда вы добавляете новую функциональность, не нарушая обратной совместимости.ПАТЧ-версию, когда вы делаете обратно совместимые исправления. Если мы постоянно будем указывать конкретную версию пакета, зависимости проекта разрастутся, и мы будем хранить лишнее количество версий пакетов, которые отличаются между собой незначительными правками. Если нам подходит любая минорная версия, начиная с 1.2.3 (т.е. диапазон с 1.2.3 до 1.3.0 (не включая)), то мы можем указать "is-odd": "~1.2.3" Подсказка, как читать версии пакета. Наглядно посмотреть какие версии какого пакета входят в диапазон. В ходе работы над проектом добавляются, удаляются и обновляются пакеты, решаются конфликты в зависимостях, в библиотеках находят уязвимости и lockfile может содержать ошибочно старые версии или дубликаты. А могут быть даже никем не используемые пакеты. Выходят новые версии библиотек, содержащие уязвимости (так бывает), все это нужно решать. Избавимся от лишнего. Самое простое, что мы можем проверить – это используется ли библиотека. Проверять использование можно вручную, а можно с помощью depcheck, он сообщит о том, как используется зависимость, есть ли неиспользуемые пакеты и тд.  Например, команда мигрировала с final-form на formik, весь код уже переписали – а final-form забыли удалить. Final-form есть в зависимостях, но не используется. Если в коде осталось буквально пару мест использования старой библиотеки — можно их дорефакторить и со спокойной душой убирать зависимость. Решим уязвимости. Иногда достаточно просто обновить версию или перейти с deprecated пакета на новый. Команда yarn audit подсветит все уязвимости, распределив и по 5 уровням критичности, укажет в какой версии пакета это наблюдается, какой версией решается. Эти данные также доступны на npm.js.com. Но фиксить придется руками. npm audit --fix умеет автоматически фиксить уязвимости. Однако, если проект большой — это стоит делать очень осторожно. Примечание. Yarn не имеет такой команды, но можно воспользоваться костылём подобным инструментом. yarn upgrade <package_name> — принудительный апгрейд пакета. Если не указывать версию, yarn подберет последнюю, указанную в package.json. Upgrade может принимать версию и в качестве параметра, но тогда он никак не опирается на package.json. Решим дубликаты. Конечно, yarn пытается оптимизировать всё, но нет идеального алгоритма поиска дубликатов пакетов: пакеты is-odd@1.2.2 и is-odd@1.2.3 могут быть дважды установлены, хоть и практически не отличаются между собой. Способ 1. Удалить lockfile (опасно). Очищаем node_modules, удаляем lockfile и запускаем yarn install, пакетный менеджер попробует построить дерево зависимостей с нуля, подтянет все новейшие версии в рамках semver. Все же так когда-нибудь делали? Так мы получим новое дерево зависимостей, но есть высокая вероятность сломать поведение. Где-то могли произойти breaking changes, из-за возможного обновления библиотек (т.к. yarn.lock файла с указанными версиями больше нет), которые потребуют правок в коде. А что ещё хуже, мы могли притянуть новые версии, которые уже не совместимы с нашим проектом, например обновить библиотеку, зависимую от старого react, на версию, которая полностью зависит от нового. Способ 2. Yarn dedupe. В yarn2 есть команда dedupe, которая позволяет автоматически убирать дубликаты. Можно выбрать стратегию избавления от дубликатов. Способ 3. Резолюции. В package.json мы можем указать какие версии зависимостей хотим видеть в нашем проекте. Это бывает удобно, когда сторонняя библиотека использует подзависимости, которые мы хотим обновить. Например, пакет icons-classic, зависит от browserlist (который, к примеру, содержит уязвимости). Дабы не ждать разработчиков icons-classic, мы можем сами поднять/опустить версию browserlist до необходимой. Если указываешь какую-то версию зависимостей своего пакета, то не обязательно будет стоят она. Это важно, потому что часто порождает нежелательное поведение. Зависимости надо оптимизировать самостоятельно, хоть в yarn все автоматизированно, есть крайние случаи, когда требуется человеческий взгляд. Этот инструмент самостоятельный, но когда понимаешь зачем — можно тонко настроить.  И самое главное: периодически «прочесывать» зависимости – полезная практика, если проект намеревается долго жить. Полезные ссылки: Как обращаться с зависимостями. Как читать версии пакета. Наглядно посмотреть какие версии какого пакета входят в диапазон. Инструмент для проверки зависимостей — depcheck. База данных уязвимостей безопасности GitHub. Преобразовать yarn.lock в package-lock.json и обратно. Обновить пакеты до последней версии. Yarn dedupe. Подборка от редактора блога: RTK query: что мы от него хотим и зачем Ещё одна подборка книг по фронтенду Скаутинг, fast track, пилоты, инновации? «Гигиенический минимум» в работе тимлида