Как работает package.json?
Файл package.json позволяет указать диапазон версий пакетов, которые нужно ставить. Это нужно, чтобы не следить вручную за появлением новых версий пакетов. Разработчики договорились между собой, что будут использовать семантическое версионирование при создании пакетов:
- X.1.1 , где X — это мажорная версия, которая может содержать несовместимые с предыдущей версией изменения
- 1.X.1 , где X — это минорная версия, которая скорее всего содержит совместимые с предыдущей версией изменения
- 1.1.X , где X — это патч-версия, которая содержит различные исправления
Зачем это нужно? Бывает, что нужно создать что-то кардинально новое, но при этом не помешать пользователям работать со старой версией. Старая и новая версия могут иметь совершенно разный интерфейс, функции и требования. Например, требования к языку или интерпретатору. Но при этом иногда обнаруживаются баги в старой версии и её нужно поддерживать. Соответственно вносятся изменения и в старую, и в новую версию.
Возьмем для примера пакет с версией 1.0.0. Спустя время у него появилась версия 1.2.3. Разработчики решили, что хотят что-то кардинально поменять и выпускают новую версию 2.0.0. Но на старой версии нашли уязвимость, к ней выпустили патч — версия поднялась до 1.2.4.
Но что если сегодня установим проект на наш комп, а завтра на продакшен, а в это время версии пакетов случайно обновятся и что-то сломается? Это неудобно. Поэтому существуют лок-файлы (package.lock), в котором фиксируется версия пакетов. Именно эта версия будет устанавливаться в каждом запуске, пока мы обновим package.lock.
Когда мы хотим установить зависимости, мы можем использовать npm install или npm ci (Clean Install). Разница между ними следующая:
- npm install создаст lock-файл, если его нет. Для npm ci лок-файл обязателен
- Если зависимости в package.json и package.lock не совпадают, то npm ci упадет с ошибкой
- npm ci ставит все зависимости, npm install позволяет поставить зависимости индивидуально (добавить в package.json)
- Если директория node_modules существует, то npm ci её удалит, зависимости поставятся с нуля
Если необходимо, то пакеты можно обновить командой npm update , либо изменив package.json и выполнив npm install
Зачем нужен package lock json и package json


В данной статье мы хотим познакомить вас с package lock и package json файлами. Разберемся, для чего необходимы lock файлы, при работе с npm.
Давайте начнём с npm (node-modules) — это сборщик пакетов в программной платформе node.js. Актуальную версию node.js можно скачать по ссылке. В основном предназначена для установки модулей. Для просмотра актуальных версий модулей npm создаёт файл package.json.
Что такое пакет в JavaScript?
Пакетом называется один или несколько файлов в JS, в виде инструмента или библиотеки. Npm хранит в себе самый большой набор пакетов. Npm необходим для скачивания пакетов и загрузки их, благодаря этому можно хорошо ускорить своё написание кода.
Что такое package.json?
Package.json — это файл, который представляет зависимости верхнего уровня от других пакетов при помощи семантического управления версиями. Любой пакет, может исходить из другого пакета, у них образуется взаимосвязь.
Package.json файл состоит:
1. Dependencies (зависимости) в которых хранятся названия и версия модуля
2. Метаданные — это описание, автор, лицензия и т.д.
3. Скрипты
Типы зависимостей в package.json
Давайте разберем несколько основных зависимостей проекта, чтобы лучше понимать что в него входит и что можно редактировать.
• dependencies — главные зависимости которые находятся в вашем проекте. Их можно применять и запускать в коде.
• devDependencies — взаимосвязи разработки.
• peerDependencies — равные взаимосвязи, при добавлении которых, мы даем понять какую версию для взаимосвязи следует установить
• optionalDependencies — второстепенные зависимости. Если при установке произойдет сбой, на основную сборку это не повлияет.
• bundledDependencies — в нём содержится массив пакетов. Данный массив нужен, если вам требуется добавить новую зависимость, которой нет в npm.
Назначение package-lock.json
package-lock.json если коротко, то предназначен для блокировки зависимостей от определенного номера версии. В package-lock.json файле перечислены зависимости вашего приложения и зависимости всех его зависимостей. Другими словами, он описывает, какую версию каждого отдельного пакета вы установили. Вот почему это намного дольше, чем package.json. Когда вы используете package-lock.json для установки зависимостей, вы получаете точно такие же пакеты, неважно, устанавливаете ли вы их сейчас или через несколько лет, когда мы, надеюсь, больше не будем использовать клавиатуры.
Чтобы установить зависимости на основе текущего package-lock.json файла, вы должны использовать npm ci вместо npm install.
Используя, npm ci вы сможете избежать проблем, которые возникают, когда приложение работает на вашем компьютере, но не работает на чужом, потому что они в конечном итоге загрузили различные зависимости из-за использования npm install.
Вот почему при запуске ваших сборок на сервере непрерывной интеграции вам следует устанавливать зависимости, используя npm ci вместо npm install. Это приведет к тому, что сборка CI-сервера будет работать так же, как на вашем компьютере.
Назначение package.json
Как говорилось уже выше, файл package.json — один из основных частей проекта основан на Node.js. Многие уже встречали этот файл у себя в проектах, но открыв его — ничего не поняли, так и остался для вас “тёмным туманом”. Зачем использовать данный файл?
Package специализирован не только лишь на взаимосвязях, но и для определения свойств проекта:
Чтоб отключить автоматическое создания файла следует написать в npmrc package-lock=false. Наличие package-lock.json в проекте необязательно.
Разбивка параметров
- name — параметр name обозначает имя создаваемого проекта. Имя не должно превышать 214 знаков. Запрещены пробелы, подчеркивания, дефисы и CAPS LOCK.
- Зачем нужно столько ограничений? После создания пакета происходит генерация url страницы.
- author — описание об авторе проекта. Может быть имя, фамилия. Может быть представлен в виде массива с указаниями соц. сетей.
- contributors — люди, которые разрабатывали данный проект (массив)
- bugs — Отслеживание багов в проекте, можно указать ссылку на GitHub трекер.
- homepage — Главная страница пакета
- version — Указывает текущую версию пакета.

Правила написания версии:
Первая цифра — это внесены критические изменения
Вторая цифра — обозначает, что выпуск содержит новые функции.
Третья цифра — указывает на исправления.
- license — лицензия пакета
- keywords — ключи(теги) для поиска вашего проекта. Чем лучше их задать, тем легче людям найти ваш пакет.
- description — описание проекта. Если выкладывать в сеть, то данное описание обязательно!
- repository — добавьте сюда git репозиторий пакета. Данное свойство содержит префиксы (gitlab:url, bitbucket:url)
- main — Главная файл пакета
- private — если значение true, то оно не даст загрузить набор в npm
- scripts — скрипты, которые могут быть доступны через npm
- dependencies — перечень установленных взаимосвязей
- devDependencies — зависимости разработки
- engines — показывает, какие средства и версии Node.js употребляться для работы пакета
- browserslist — помогает показать, какие браузеры могут поддерживать пакет
Менеджеры версий
Существует несколько возможностей, разрешающих пользоваться многими версиями Node.js на вашем пк. Одна из них n, вторая — Node Version Manages(nvm). Кто искал данное решение, изучите информацию на ресурсах: Install Multiple Versions of Node.js using nvm.
Что из себя представляет расширение JSON
Формат JSON — это текстовый формат служит для обмена данными созданный на объектах JS. Данные в файле представлены в виде “ключ — значение”.
Как создать package.json?

Из-за того, что package.json довольно глобальный и состоит из множества свойств, то в ручную его писать трудно и очень долго. Для быстроты решения задачи, npm сделали команду init. Откройте консоль в области текущей папки и напишите команду: npm init. Данная команда позволяет создать файл package.json. После этого вы получаете вот такой ответ:
Затем после всех вопросов, в основном вы все пропускаете через Enter, мы получаем те самые данные в виде “ключ — значение”

Наш package.json создан!
Установка модулей
Для начала в своём проекте в консоли напишите команду
npm install
Данная команда установит файл node_modules(короткий вариант команды npm i). Вторым этапом мы установим какую-нибудь библиотеку. К примеру: gulp-sass — помогает скомпилировать код, и сжать стили. Для установки напишем команду
npm install gulp-sass —save
Если вам нужны еще библиотеки просто перечисляете их, отделяя отступом. Но не забывайте добавлять аргумент —save, для сохранения библиотеки как зависимость самого проекта.
Аргумент —save показывает npm следить за актуальной версией package.json. Хорошая возможность, дать другим разработчиком увидеть какие зависимости необходимы проекту.
По итогу у нас получились созданные файлы: package.json, package-lock.json, node_modules.
Сгенерированная папка node_modules хранит в себе все модули вашего проекта. Данную папку в Git репозиторий мы не добавляем! Так как в ней хранится множество зависимостей и они будут только добавляться, вы будете очень долго ждать загрузки. Загружать нужно только 2 файла package.json, package-lock.json, даже после того, как другой разработчик сделает копию вашего проекта, он сможет установить нужные зависимости сохраненные в package.json.
Не забудьте добавить файл node_modules в gitignore.
Заключение
По итогу, в данной статье мы разобрали базу package и package lock, рассказали о самых распространенных и часто встречающихся ошибках, которые следует избегать.
Углубились в структуру файлов. Показали как установить node_modules, а также научились устанавливать дополнительные библиотеки.
В конечном итоге помните, что на git node_modules лучше не добавлять. И теперь любой скопированный проект вы сможете настроить сами, так, чтобы он работал.
Для чего нужен package-lock.json?
Доброе время суток. Я почитал документацию к NPM, почитал форумы, но всё равно до конца не совсем понимаю, смысловую нагрузку этого файла. Вот то что описано на npm документации:
Этот файл предназначен для фиксации в исходных хранилищах и предназначен для различных целей: 1) Описывает единственное представление дерева зависимостей, чтобы товарищи по команде, разворачивая проект гарантированно установил одинаковые зависимости. 2) Предоставьте пользователям возможность «путешествовать во времени» к предыдущим состояниям node_modules без фиксации самого каталога. 3) Для облегчения большей видимости изменений в дереве с помощью читаемых исходных текстов контроля. 4) И оптимизировать процесс установки, позволяя npm пропускать повторяющиеся установленные пакеты.
Вопрос сразу по 1 пункту, ибо у меня package.json и package-lock.json не в гит игноре! Они комитятся. И как написано в той же документашке, когда мы делаем npm i , пакетный менеджер устанавливает зависимости, которые описаны в файле package.json . И скачав очередную библиотеку мы идем внутрь неё и устанавливаем её зависимости (и так рекурсивно). На данном этапе в package-lock.json просто выводится информация какие внутренние зависимости основных библиотек мы скачали. Как оно помогает «гарантированно установил одинаковые зависимости» ? И это всё полностью вытекает из 3 пункта. Ну и согласен с 4 пунктом, по факту если в node_modules уже есть такой пакет (с той же версией и хешем), то его устанавливать не будут. НО, опять же эту инфу можно смотреть не по package-lock.json , а в зависимостях основного пакета, ибо почти у каждой либы есть внутренний package.json . Т.е нам не нужен промежуточный файл получается. Верно ли я все понимаю? Пожалуйста, поправьте!
Что такое package.json?
package.json — это файл управления версиями. Его основное назначение — хранить список зависимостей (библиотек), необходимых проекту node.js для работы. Он также включает другую метаинформацию, в том числе скрипты, данные об авторе и лицензии, описание и свойства проекта.
Проблема
В приведенном выше package.json видно, что объект “dependencies” сопоставляет имя пакета с диапазоном версий.
Файл package.json всегда предоставляет диапазон версий для зависимости, но никогда — точную версию.
Это делает npm install недетерминированной командой. Поэтому, если запустить npm install cегодня, а затем запустить ее снова через 3 месяца, можно получить не то же самое дерево node_modules .
Кроме того, если другой разработчик клонирует проект и через несколько дней запустит npm install , у него может оказаться другое дерево зависимостей node_modules . Когда несколько разработчиков работают над одним и тем же репозиторием (что чаще всего и происходит в каждой организации), это может стать большой проблемой и привести к несоответствию установленных зависимостей или, что еще хуже, к критическим изменениям.
Каково же решение этой проблемы? Для начала разберемся, что означает диапазон версий. Строка, содержащая одно или несколько чисел, разделенных пробелами, называется диапазоном версий. Эти числа также содержат некоторые специальные символы, такие как ^ ~ < || . Например, ^1.0.4, ~2.3, 4.4.x, >=2.3.4,
Эти символы передают npm разные команды.
Допустим, требуется установить пакет “foo” . После запуска npm i foo в файле package.json появится запись следующего содержания:
"dependencies": "foo": "^2.3.0",
.
.
>
>
Здесь установлен “foo” версии 2.3.0 [major minor patch] . Символ каретки несет в себе определенную информацию.
^2.3.0 [^ — символ каретки] — указание npm обновить версию до минорной (второстепенной) версии и патча, но не до мажорной (основной) версии. То есть 2.3.4, 2.3.9, 2.4.5, 2.8 , но не 3.0.0 и т. д.
~2.3.0 [~ — символ тильды] — указание npm обновлять до версии патча, но не до минорной и мажорной версий. То есть 2.3.4, 2.3.9 , но не 2.4.0 и т. д.
Есть множество других символов, обозначающих различные стратегии обновления версий npm. Лучшим справочником в этом отношении является официальный сайт npm.
Итак, при запуске npm install несколько дней спустя версия «foo»: «^2.3.0» (на данный момент минорная/патч) может автоматически обновиться, что нежелательно. Но не волнуйтесь: на помощь придет package-lock.json.
Что такое package-lock.json?
package-lock.json — это лок-файл (файл блокировки), содержащий информацию о зависимостях/пакетах с их точными номерами версий (*важно), которые были установлены для проекта node.js.
- Это помогает членам команды, работающим над одним и тем же репозиторием, инсталлировать именно те версии пакетов, которые были установлены ранее, даже если для пакетов были выпущены новые версии. Это обеспечивает одинаковое дерево node_modules на разных компьютерах/средах.
- Файл package-lock.json используется для фиксации зависимостей к определенному номеру версии.
- Этот файл автоматически генерируется (или воспроизводится) при изменении дерева node_modules или файла package.json .
- Всякий раз при клонировании репозитория и запуска npm i на новом компьютере, npm сначала обратит внимание на наличие файла package-lock.json . При обнаружении он начнет установку пакетов, указанных в этом файле. В противном случае заглянет в файл package.json и начнет установку необходимых зависимых пакетов (разъяснение на этот счет будет далее в этой статье).
Нужно ли коммитить package-lock.json?
Да, этот файл должен быть зафиксирован в исходном репозитории, чтобы при клонировании репозитория разработчики могли инсталлировать зависимости, точно соответствующие тем, которые были первоначально установлены на компьютере/в среде. В основном это делается для репликации сред node.js, установленных на разных компьютерах.
Начиная с npm v7 , lockfile (лок-файл) содержит достаточно информации обо всем дереве пакетов, что снижает необходимость чтения файлов package.json и тем самым увеличивает производительность.
Почему/когда npm install переписывает package-lock.json?
Разъяснение: npm install учитывает package-lock.json , только если устанавливаемый пакет(ы) находится в диапазоне версий package.json .
Если версия пакета, указанная в лок-файле, не входит в диапазон версий файла package.json , пакеты обновляются, а package-lock.json перезаписывается. Чтобы вместо перезаписи package-lock.json установка завершилась неудачей, используется npm ci .
Пример
Вы объявляете зависимость в package.json следующим образом:
"foo": "^2.3.0"
Затем выполняете команду npm install , которая создаст package-lock.json с версией:
"foo": "2.3.0"
Через несколько дней выходит более новая минорная версия “foo” , например 2.4.0, и тогда происходит следующее.
npm install : версия package-lock находится в пределах диапазона (т.е. ^2.3.0), поэтому устанавливается 2.3.0.
npm ci : в любом случае учитывается только package-lock.json , поэтому устанавливается 2.3.0.
Далее необходимо вручную обновить package.json до:
"foo": "^2.4.0"
Затем повторите запуск.
npm install : версия package-lock не входит в диапазон (т.е. ^2.4.0), поэтому устанавливается 2.4.0, а package-lock.json переписывается и теперь показывает «foo»: «2.4.0» .
npm ci : эта команда в любом случае учитывает только package-lock.json, но поскольку версия не находится в диапазоне, она выдает ошибку.
Команда npm ci похожа на npm install за исключением того, что она предназначена для использования в автоматизированных средах, таких как тестовые платформы, непрерывная интеграция и развертывание, или в любой другой ситуации, когда нужно убедиться, что выполняется чистая установка зависимостей (npm docs).
Выводы
- npm install не является детерминированной командой, что создает проблему при работе над репозиторием (с несколькими разработчиками), содержащим тысячи зависимостей.
- Файл package-lock.json гарантирует, что при каждом запуске npm install будет создаваться одно и то же дерево node_modules .
- Более новая команда npm ci гарантирует, что ВСЕГДА будет создаваться одно и то же дерево node_modules . В противном случае происходит ошибка.
- Как выбрать подходящую версию Node.js?
- 5 библиотек ведения логов для Node.js
- Однопоточность и асинхронность: как у Node это получается?
Читайте нас в Telegram, VK и Дзен