Более умные обновления пакетов с npm-check-updates
Дрейф зависимостей медленно убивает проекты. Вы пропускаете несколько обновлений, потом ещё несколько, и внезапно перед вами 47 устаревших пакетов — половина с breaking changes, некоторые с уязвимостями безопасности, и нет чёткого пути вперёд. Запуск npm update напоминает русскую рулетку. Массовые обновления ломают CI. Безопасным выбором становится бездействие, которое вовсе не безопасно.
npm-check-updates (ncu) предлагает другой подход: разделение решения о том, что обновлять, от процесса установки и тестирования. Это различие имеет большее значение, чем осознают большинство команд.
Ключевые выводы
- ncu изменяет диапазоны версий в package.json без изменения node_modules или lockfile, давая вам контроль над моментом установки
- Используйте
--target minorили--target patchдля ограничения обновлений до изменений без breaking changes - Флаг
--peerпредотвращает предложение обновлений, которые вызовут конфликты peer-зависимостей - Всегда коммитьте package.json и package-lock.json вместе после тестирования обновлений
- Используйте поле
overridesв npm для принудительной установки конкретных версий транзитивных зависимостей при устранении уязвимостей
Почему слепые обновления ломают сборки
Основная проблема управления пакетами JavaScript не в поиске устаревших зависимостей — с этим справляется npm outdated. Проблема в том, что обновление до “latest” игнорирует ограничения peer-зависимостей, границы semver и реальность того, что ваш lockfile существует не просто так.
Когда вы запускаете npm update, npm соблюдает диапазоны версий в вашем package.json. Он не перейдёт с ^2.0.0 на 3.0.0, даже если версия 3 существует. Это сделано намеренно. Но это также означает, что настоящие обновления, требующие изменения диапазонов, застревают на неопределённый срок.
ncu решает это путём прямого изменения package.json — обновления диапазонов версий — без изменения node_modules или вашего lockfile. Вы контролируете, когда происходит установка.
Современные рабочие процессы ncu для управления зависимостями Node.js
Глобальные установки больше не являются моделью по умолчанию. С ncu v18+ запускайте его напрямую через ваш менеджер пакетов:
npx npm-check-updates
# или
pnpm dlx npm-check-updates
# или
bunx npm-check-updates
Это проверяет наличие обновлений без изменения чего-либо. Вы видите, что доступно, с цветовой кодировкой по уровню semver: красный для major, голубой для minor, зелёный для patch.
Критический флаг — это -u, который записывает изменения в package.json. Но вот что важно: это обновляет только манифест. Ваш lockfile остаётся неизменным, пока вы явно не запустите npm install.
Это разделение обеспечивает более безопасный рабочий процесс обновления зависимостей:
- Запустите
ncu -u --target minorдля обновления package.json с изменениями без breaking changes - Запустите
npm installдля регенерации lockfile - Запустите ваш набор тестов
- Если тесты проходят, закоммитьте package.json и package-lock.json вместе
Для major-обновлений обрабатывайте их индивидуально с помощью ncu -u --filter package-name, просмотрите changelog, затем протестируйте.
Discover how at OpenReplay.com.
Peer-зависимости и проверка совместимости
Конфликты peer-зависимостей вызывают большинство сбоев при обновлении. Библиотека компонентов React может требовать React 18, но ваш проект закреплён на React 17. Слепое обновление библиотеки ломает сборку.
Флаг --peer в ncu проверяет совместимость peer-зависимостей перед предложением обновлений. Это предотвращает предложение обновлений, которые немедленно провалят установку.
Для более строгого контроля комбинируйте это с --target:
ncu --peer --target minor
Это показывает только обновления, которые не нарушат ограничения peer-зависимостей и не пересекут границы major-версий.
Lockfile и интеграция с CI-пайплайнами
Ваш lockfile представляет известное рабочее состояние. Относитесь к нему соответственно.
В CI всегда используйте npm ci вместо npm install. Команда ci завершается с ошибкой, если package.json и package-lock.json рассинхронизированы — именно то, что вам нужно. Это выявляет ситуации, когда кто-то обновил package.json, но забыл регенерировать lockfile.
Для автоматизированных рабочих процессов обновления зависимостей в CI паттерн выглядит так:
ncu -u --target patch
npm install
npm test
Если тесты проходят, пайплайн коммитит изменения. Если они не проходят, обновление помечается для ручной проверки.
Контроль транзитивных зависимостей с помощью Overrides
Иногда проблема не в ваших прямых зависимостях — а в том, от чего зависят они. Уязвимость на три уровня глубже в дереве зависимостей требует обновления пакета, которым вы не управляете.
Поле overrides в npm позволяет принудительно установить конкретные версии транзитивных зависимостей:
{
"overrides": {
"vulnerable-package": "2.0.1"
}
}
Это стандартная часть управления пакетами JavaScript. Используйте это, когда вам нужен патч безопасности до того, как upstream-мейнтейнеры обновят свои зависимости.
Заключение
Автоматизация обновления зависимостей не означает постоянное обновление всего. Это означает наличие повторяемого процесса, который разделяет обнаружение и установку, соблюдает границы semver и поддерживает синхронизацию вашего lockfile с манифестом.
ncu подходит для этого рабочего процесса, потому что рассматривает обновления package.json как отдельный шаг. Вы решаете, что обновлять, когда устанавливать и когда тестировать. Инструмент обрабатывает рутинную часть — проверку реестров и изменение диапазонов версий — оставляя оценочные решения вам.
Обновляйте патчи еженедельно. Проверяйте minor-версии ежемесячно. Обрабатывайте major-версии обдуманно. Держите ваш lockfile в коммитах. Ваш CI скажет вам спасибо.
Часто задаваемые вопросы
npm update устанавливает более новые версии в пределах существующих диапазонов версий в вашем package.json, но не пересечёт границы major-версий. npm-check-updates изменяет сами диапазоны версий в package.json, позволяя обновляться до любой версии, включая major-релизы. ncu изменяет манифест, в то время как npm update изменяет node_modules.
Да. ncu работает с любым менеджером пакетов, так как изменяет только package.json. Запустите его с помощью pnpm dlx npm-check-updates или npx npm-check-updates независимо от вашего менеджера пакетов. После того как ncu обновит ваш package.json, используйте предпочитаемый менеджер пакетов для установки обновлённых зависимостей.
Используйте флаг reject с именем пакета или паттерном. Например, ncu --reject typescript исключает TypeScript из обновлений. Вы также можете использовать ncu --reject '/react.*/' для исключения нескольких пакетов, соответствующих паттерну. Это полезно для пакетов, которые вы хотите обновлять вручную.
Запуск ncu -u только изменяет package.json без установки чего-либо. Риск возникает при последующем запуске npm install без тестирования. Всегда запускайте набор тестов после обновления и установки. Начните с patch-обновлений, используя ncu -u --target patch для наиболее безопасного подхода.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.