Пошук уроків, статей та іншого контенту
Розберемо призначення package-lock.json, фіксацію дерева залежностей і відтворюваність встановлення.
package-lock.jsonpackage-lock.json — файл, який npm створює для фіксації точного дерева залежностей проєкту.
У package.json зазвичай записують діапазони версій:
{
"dependencies": {
"lodash": "^4.17.0"
}
}Символ ^ означає, що npm може встановити сумісну версію, наприклад 4.17.21. Через деякий час у реєстрі може з’явитися нова версія, яка також відповідає цьому діапазону.
package-lock.json зберігає конкретний результат встановлення:
точні версії пакетів;
транзитивні залежності;
джерела завантаження пакетів;
контрольні суми пакетів;
структуру залежностей;
деякі параметри встановлення.
Тому два розробники або сервер CI можуть отримати однакове дерево залежностей.
Припустімо, що проєкт без змін у package.json встановлюється через кілька місяців. За цей час залежності могли оновитися в межах указаних діапазонів версій.
Без package-lock.json результат може відрізнятися:
Сьогодні: lodash 4.17.20
Через місяць: lodash 4.17.21Навіть patch-оновлення іноді можуть вплинути на поведінку застосунку.
З lock-файлом npm отримує вже визначене дерево:
lodash 4.17.21
└── точна версія зафіксована в package-lock.jsonЦе дає:
передбачуване локальне встановлення;
однакові залежності на різних машинах;
стабільні збірки в CI/CD;
можливість відстежувати зміни залежностей у Git;
контроль над транзитивними залежностями.
package-lock.jsonФайл створюється або оновлюється командою npm install.
Приклад нового проєкту:
# Створення каталогу проєкту
mkdir lock-demo
cd lock-demo
# Створення package.json
npm init -y
# Встановлення залежності
npm install lodash@^4.17.0
# Перевірка встановленої версії
node -e "const lock = require('./package-lock.json'); console.log(lock.packages['node_modules/lodash'].version)"Після виконання команд у каталозі будуть створені:
package.json
package-lock.json
node_modules/У package.json npm запише діапазон:
{
"dependencies": {
"lodash": "^4.17.0"
}
}А в package-lock.json буде записана конкретна встановлена версія та її метадані. Фрагмент сучасного lock-файлу може мати такий вигляд:
{
"name": "lock-demo",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "lock-demo",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"lodash": "^4.17.0"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-..."
}
}
}integrity у прикладі скорочено. У справжньому файлі це повне значення контрольної суми.
package-lock.jsonЦе пакети, які вказані безпосередньо в package.json:
{
"dependencies": {
"express": "^4.18.0"
}
}Це залежності самих залежностей.
Наприклад:
ваш застосунок
└── express
├── body-parser
├── cookie
└── ...Ви могли не вказувати body-parser у власному package.json, але його версія також важлива для результату встановлення. Lock-файл зберігає і такі пакети.
У package.json може бути:
{
"dependencies": {
"lodash": "^4.17.0"
}
}У lock-файлі:
{
"version": "4.17.21"
}Саме точна версія з lock-файлу використовується під час відтворення встановлення.
Поля resolved та integrity допомагають npm:
завантажити пакет із правильного джерела;
перевірити, що отриманий архів не пошкоджений і відповідає очікуваному вмісту.
npm install і npm ciДля роботи з lock-файлом важливо розрізняти ці команди.
npm installnpm install призначена переважно для розробки.
Вона може:
встановити залежності;
створити package-lock.json, якщо його ще немає;
оновити lock-файл;
змінити lock-файл після зміни package.json;
додати новий пакет.
Якщо package.json і package-lock.json сумісні, npm зазвичай використовує зафіксовані версії. Якщо ви явно додаєте або оновлюєте залежність, lock-файл може змінитися.
npm install
npm install axios
npm install lodash@latestnpm cinpm ci призначена для чистого та відтворюваного встановлення, особливо в CI/CD.
Вона:
вимагає наявності package-lock.json;
перевіряє узгодженість package.json і lock-файлу;
видаляє наявний каталог node_modules;
встановлює залежності за lock-файлом;
не оновлює package-lock.json.
Приклад повного сценарію:
# Встановлення залежностей за lock-файлом
npm ci
# Запуск застосунку або тестів
npm testЯкщо package.json змінено, але lock-файл не оновлено, npm ci завершиться з помилкою. Це корисна перевірка: CI виявляє, що зміни залежностей не були зафіксовані повністю.
Відтворюваність означає, що за однакових умов команда встановлення отримує однаковий набір залежностей.
Типовий процес такий:
Розробник змінює залежності.
npm оновлює package-lock.json.
Обидва файли додаються до Git.
Інший розробник або CI виконує npm ci.
Встановлюється дерево, описане в lock-файлі.
У репозиторій зазвичай додають:
package.json
package-lock.jsonА каталог node_modules не додають:
node_modules/node_modules може бути великим, залежить від операційної системи та не потрібен для відтворення встановлення.
У package-lock.json є поле lockfileVersion. Воно визначає формат файлу, який використовує певна версія npm.
Формат міг змінюватися між версіями npm. Через це різні версії npm іноді:
перегенеровують lock-файл;
змінюють lockfileVersion;
створюють великий diff без зміни самих залежностей;
не можуть повністю працювати з новішим форматом.
У командній роботі бажано узгодити версії Node.js та npm. Це зменшує кількість непотрібних змін у package-lock.json.
Перевірити версії можна командами:
node --version
npm --versionpackage-lock.json потрібно комітити разом зі змінами залежностей.
Наприклад, після встановлення нового пакета зміни мають охоплювати обидва файли:
modified: package.json
modified: package-lock.jsonЯкщо залежність була видалена:
npm uninstall lodashnpm оновить і package.json, і package-lock.json.
У команді корисно перевіряти, чи немає незакомічених змін:
git diff -- package.json package-lock.jsonLock-файл — це не службовий тимчасовий файл. Його зміни є частиною зміни залежностей проєкту.
Оновлюйте package-lock.json, коли:
додаєте залежність;
видаляєте залежність;
змінюєте потрібну версію;
оновлюєте залежності свідомо;
змінюєте версію npm і приймаєте новий формат lock-файлу.
Не потрібно вручну редагувати версії в lock-файлі. Для цього використовуйте npm-команди:
npm install package-name@version
npm update package-name
npm uninstall package-namepackage-lock.jsonЯкщо додати lock-файл до .gitignore, кожен учасник команди може отримувати інші версії транзитивних залежностей.
Для застосунку, який встановлюється через npm, package-lock.json зазвичай має зберігатися в репозиторії.
npm install у CI без потребиnpm install може оновити lock-файл або встановити новіші сумісні версії.
Для CI зазвичай використовують:
npm ciЦе робить встановлення строгішим і виявляє невідповідність між двома manifest-файлами.
package-lock.json має складну структуру. Ручна зміна одного поля може зробити дерево залежностей некоректним.
Краще змінити залежність через npm і дозволити npm перегенерувати необхідні записи.
package.jsonЯкщо додати до Git тільки package.json, а package-lock.json не додати, інші середовища не матимуть зафіксованого дерева залежностей.
Зміни залежностей потрібно комітувати разом:
package.json
package-lock.jsonРізні версії npm можуть по-різному форматувати lock-файл. Якщо розробники постійно запускають різні версії npm, у Git з’являються великі й неочікувані зміни.
Варто використовувати узгоджене середовище виконання та однакову команду встановлення.
Видалення package-lock.json і повторний npm install може приховати справжню причину проблеми та оновити багато залежностей одночасно.
Краще спочатку:
перевірити повідомлення про помилку;
виконати npm ci;
перевірити сумісність package.json і lock-файлу;
оновлювати конкретну залежність цілеспрямовано.
package.json описує бажані залежності та діапазони їхніх версій.
package-lock.json фіксує точне дерево прямих і транзитивних залежностей.
Lock-файл забезпечує передбачуване встановлення та стабільні збірки.
npm install може створювати й оновлювати package-lock.json.
npm ci встановлює залежності за lock-файлом і не змінює його.
package-lock.json потрібно зберігати в Git разом із package.json.
Не слід редагувати lock-файл вручну або без потреби видаляти його.