Почему "npm install" перезаписывает package-lock.json?
Я недавно обновился до npm@5. Теперь у меня есть файл package-lock.json, который содержит все зависимости из package.json. Я ожидал, что при запуске команды npm install
версии зависимостей будут подтягиваться из lock-файла для определения того, что должно быть установлено в моем каталоге node_modules. Однако странно, что в процессе установки мой файл package-lock.json фактически модифицируется и перезаписывается.
Например, в lock-файле была указана версия typescript 2.1.6. Однако после запуска команды npm install
версия изменилась на 2.4.1. Это кажется противоречащим самой сути lock-файла.
Что я упускаю? Как заставить npm действительно уважать мой lock-файл?
5 ответ(ов)
Краткий ответ:
npm install
учитываетpackage-lock.json
только в том случае, если он соответствует требованиям изpackage.json
.- Если требования не удовлетворяются, пакеты обновляются, и
package-lock.json
перезаписывается. - Если вы хотите, чтобы установка завершалась с ошибкой вместо перезаписи
package-lock.json
, используйтеnpm ci
.
Вот сценарий, который может прояснить ситуацию (проверено на NPM 6.3.0)
Вы объявляете зависимость в package.json
следующим образом:
"depA": "^1.0.0"
После этого выполняете npm install
, что сгенерирует package-lock.json
с:
"depA": "1.0.0"
Через несколько дней выходит новая минорная версия depA
, скажем, 1.1.0
, и тогда будет верно следующее:
npm ci # учитывает только package-lock.json и устанавливает 1.0.0
npm install # также учитывает версию из package-lock и оставляет 1.0.0 установленным
# (то есть, когда существует package-lock.json, он имеет приоритет над package.json)
Далее вы вручную обновляете свой package.json
до:
"depA": "^1.1.0"
Затем снова выполняете:
npm ci # попытается учесть package-lock, который говорит 1.0.0
# но это не удовлетворяет требованию package.json "^1.1.0"
# поэтому возникнет ошибка
npm install # установит "1.1.0" (как требуется обновленным package.json)
# также перепишет версию в package-lock.json на "1.1.0"
# (то есть, когда package.json изменяется, он переопределяет package-lock.json)
В будущем вы сможете использовать флаг --from-lock-file
(или аналогичный) для установки только из файла package-lock.json
, не модифицируя его.
Это будет полезно для CI и других окружений, где важна воспроизводимость сборок.
Подробности отслеживания этой функции можно найти по ссылке: https://github.com/npm/npm/issues/18286.
Похоже, что эта проблема была исправлена в версии npm 5.4.2.
https://github.com/npm/npm/issues/17979
(Прокрутите вниз до последнего комментария в обсуждении)
Обновление
На самом деле исправление вышло в версии 5.6.0. В версии 5.4.2 была ошибка, связанная с кросс-платформенной совместимостью, из-за которой проблема все еще могла возникать.
https://github.com/npm/npm/issues/18712
Обновление 2
Смотрите мой ответ здесь: https://stackoverflow.com/a/53680257/1611058
Теперь командой, которую следует использовать для установки существующих проектов, является npm ci
.
Вероятно, вам стоит использовать что-то вроде этого:
npm ci
Вместо того, чтобы использовать npm install
, если вы не хотите изменять версию вашего пакета.
Согласно официальной документации, как npm install
, так и npm ci
устанавливают зависимости, необходимые для проекта.
Основное различие заключается в том, что
npm install
устанавливает пакеты, принимая за основу файлpackage.json
. В то время как в случаеnpm ci
установка пакетов осуществляется на основе файлаpackage-lock.json
, что гарантирует, что каждый раз устанавливается именно тот же самый пакет.
Этот сайт также содержит информацию о изменениях в package-lock при последующих выполениях команды npm i: GitHub - npm/cli#4263.
В чем разница между тильдой (~) и каретом (^) в package.json?
Как удалить модули npm в Node.js?
Как предотвратить установку "devDependencies" модулей NPM для Node.js (package.json)?
Ошибка "npm WARN package.json: Нет поля repository"
nvm постоянно "забывает" Node.js в новой сессии терминала