Код
#статьи

Что такое NPM: гайд по менеджеру пакетов для JavaScript

Разбираемся, как работает пакет с пакетами для JavaScript.

Иллюстрация: Катя Павловская для Skillbox Media

Если вы начали разрабатывать проект на Node.js, то уже наверняка заметили, что работа с библиотеками может быть сложной и выматывающей. Постоянно надо следить за тем, чтобы модули проекта не терялись, вовремя обновлялись и не конфликтовали с другими пакетами. В этой статье рассказываем про NPM — пакетный менеджер, который упрощает работу со сторонними библиотеками в JavaScript.

ЭКСПЕРТ

Владимир Вавщик

Эксперт по фронтенд-разработке в Skillbox, фрилансер.

Содержание

Знакомство с NPM

NPM (Node Package Manager) — менеджер пакетов для программной платформы Node.js. С его помощью можно устанавливать библиотеки, управлять зависимостями и редактировать метаданные проекта.

Перед началом работы с NPM надо скачать и установить пакет Node.js с официального сайта проекта. После этого нужно запустить любой интерфейс командной строки — приложение для ввода команд. Это может быть PowerShell, терминал, консоль или командная строка. Всё зависит от вашей операционной системы.

Загрузка и установка пакетов

Пакет — упакованный код, который может быть библиотекой, утилитой или полноценным приложением. Разработчики используют общедоступные пакеты, чтобы не изобретать велосипед — то есть не писать с нуля модули, которые уже давно созданы. Представьте, что вы пишете бота, который конвертирует валюты. Можно самостоятельно продумать логику модуля, который будет сверять курс, например, с сайтом Центрального банка, а можно воспользоваться уже готовым пакетом и сэкономить время.

Интерфейс репозитория пакетов NPM
Скриншот: NPM / Skillbox Media

В экосистеме Node.js пакеты устанавливаются с помощью менеджера NPM, а хранятся они в публичных репозиториях. Это значит, что любой желающий может изучить их код и принять участие в разработке. Список доступных пакетов по ключевым словам доступен на сайте NPM.

Для установки в NPM используется команда install, после которой надо указать название пакета:

npm install имя_пакета

Можно использовать краткую форму команды:

npm i имя_пакета

Если нужно установить несколько модулей, то можно сразу указать их названия:

npm install имя_пакета имя_пакета2 имя_пакета3...

Например, вот так можно установить Lodash — популярную у JS-разработчиков библиотеку для работы с массивами, строками и другими типами данных:

npm install lodash
Пакеты устанавливаются всего одной командой
Скриншот: командная строка Windows / Skillbox Media

Важно

Во время установки следите за названиями модулей, которые вы вводите в терминале, чтобы не стать жертвой тайпсквоттинга — хакерской атаки, эксплуатирующей ошибки ввода.

Представим, что в репозитории есть полезный модуль под названием express. Злоумышленники создают заражённый пакет с максимально похожим названием (например, expres) в надежде, что пользователь ошибётся во время ввода команды, не перепроверит данные и установит вирус. С помощью тайпсквоттинга злоумышленники часто распространяют ПО, которое ворует данные разработчиков, включая пароли от различных сервисов.

Установка зависимостей

Зависимости — набор пакетов, которые нужны для работы приложения. Они устанавливаются командой npm install и записываются в файл package.json в разделе dependencies.

Файл package.json можно отредактировать вручную, чтобы автоматически установить все необходимые пакеты. Сперва надо создать сам проект. Для этого с помощью команды cd перейдём к директории, в которой будет храниться папка проекта. В нашем случае это «Рабочий стол»:

cd C:/Users/User/Desktop

После этого выполним команду npm init, которая инициализирует новый проект и создаст файл package.json:

npm init
Результат выполнения команды npm init
Скриншот: командная строка Windows / Skillbox Media

Во время создания проекта NPM спросит его название, автора и версию. Важно помнить, что название должно быть в нижнем регистре, а неактуальные пункты можно пропустить. Если не хочется вводить все данные, то можно воспользоваться командой npm init -y, которая автоматически сгенерирует шаблон. В итоге в папке появится файл package.json с вот таким содержимым:

{
  "name": "test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Me",
  "license": "MIT",
  "description": ""
}

Теперь в раздел dependencies можно добавить названия пакетов с указанием версий в формате "название_пакета": "версия":

{
  "name": "test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Me",
  "license": "MIT",
  "description": "",
  "dependencies": {
  "express": "4.17.1",
  "lodash": "4.17.21",
  "gm": "1.22.0"
}
}

Сохраняем файл и выполняем команду:

npm install
Результат выполнения команды npm install
Скриншот: командная строка Windows / Skillbox Media

Менеджер NPM проверит список зависимостей, создаст файл package_lock.json и папку node_modules, в которой будут храниться скачанные модули проекта.

Автоматическое добавление зависимостей

В NPM предусмотрена возможность автоматического добавления зависимостей в файл package.json, чтобы не приходилось самостоятельно редактировать раздел dependencies. Для этого используют следующие флаги команд:

  • --save или -S — флаг, который во время установки добавляет название пакета и его версию в раздел dependencies. Важно отметить, что этот флаг нужен только в старых версиях NPM. Начиная с NPM 5 все устанавливаемые пакеты автоматически добавляются в раздел dependencies.
npm install music-metadata --save
Результат выполнения команды npm install music-metadata --save
Скриншот: командная строка Windows / Skillbox Media
  • --save-dev или -D — флаг, который во время установки добавляет зависимость в раздел devDependencies. Он нужен для перечисления пакетов, которые используются только для разработки и не нужны в финальной версии проекта. Например, это могут быть фреймворки для тестирования, линтеры или инструменты сборки.
npm install music-metadata --save-dev

Обновление пакетов

Для обновления модулей используется команда npm update. Она указывает менеджеру пакетов, что надо проверить список зависимостей в package.json и установить все доступные обновления, если нет ограничения.

Ограничения указываются в разделе dependencies с помощью символа каретки (^). Например, список зависимостей с ограничениями будет выглядеть так:

{
  "name": "test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Me",
  "license": "MIT",
  "description": "",
  "dependencies": {
  "express": "^4.17.1",
  "lodash": "^4.17.21",
  "gm": "^1.22.0"
}
}

Это значит, что NPM сможет обновить модули только до минорных версий и патчей, не трогая мажорные версии.

🛠️ Технические детали

Пакеты в NPM используют принцип семантического версионирования, когда версии записываются в формате MAJOR.MINOR.PATCH, где:

  • MAJOR (мажорная версия) — масштабные изменения, которые могут повлиять на совместимость модуля с другими пакетами и инструментами.
  • MINOR (минорная версия) — интеграция новых функций, которые не мешают продолжать использовать пакет в проекте.
  • PATCH (патч) — исправления ошибок, которые никак не влияют на функции и возможности модуля.

Если надо обновить конкретный пакет, то можно использовать команду update с указанием имени пакета:

npm update имя_пакета

Загрузка пакетов определённых версий

Если вы автоматически обновили все пакеты в проекте, а потом заметили, что в одном из них появились баги или пропали нужные функции, то в NPM можно откатиться до предыдущей версии и запретить установку обновлений.

Для начала надо узнать, какая версия шла перед злосчастным обновлением. Например, сейчас установлен пакет music-metadata 10.2.0. Список всех версий можно посмотреть в калькуляторе NPM SemVer: вводим название модуля и диапазон версий. В нашем случае это 10.x.x — все релизы мажорной версии под номером 10. Также список версий доступен на странице пакета в NPM.

Калькулятор NPM SemVer
Скриншот: NPM SemVer / Skillbox Media

Мы видим, что до 10.2.0 была версия 10.1.0, с которой у нас не возникало проблем. Открываем файл package.json и меняем номер версии music-metadata:

{
  "name": "test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Me",
  "license": "MIT",
  "description": "",
  "dependencies": {
    "express": "^4.17.1",
    "gm": "^1.22.0",
    "lodash": "^4.17.21",
    "music-metadata": "10.1.0"
  }
}

После этого выполняем команду npm install.

Запуск скриптов

В файле package.json можно указать скрипты и сложные команды, которые должны запускаться для сборки проекта или вывода ошибок. Например, разработчики используют Webpack для сборки нескольких файлов с JS-кодом в одно приложение. Для запуска сборки надо выполнить следующую команду:

NODE_ENV=production webpack -p --config webpack.conf.js

Эту задачу можно упростить, добавив команду в разделе scripts файла package.json. Перед командой надо добавить название скрипта, с помощью которого можно будет запустить его выполнение. В нашем случае это prod:

{
  "name": "test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "prod": "NODE_ENV=production webpack -p --config webpack.conf.js"
  },
  "author": "Me",
  "license": "MIT",
  "description": "",
  "dependencies": {
    "express": "^4.17.1",
    "gm": "^1.22.0",
    "lodash": "^4.17.21",
    "music-metadata": "10.1.0"
  }
}

После этого длинную и сложную команду можно запускать с помощью более лаконичной npm run prod.

Теперь напишем собственный скрипт, который будет выводить в терминал фразу Hello, Developer!. Для этого в раздел scripts добавим строку "say-hello": "echo 'Hello, Developer!'":

{
  "name": "test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "say-hello": "echo 'Hello Developer!'"
  },
  "author": "Me",
  "license": "MIT",
  "description": "",
  "dependencies": {
    "express": "^4.17.1",
    "gm": "^1.22.0",
    "lodash": "^4.17.21",
    "music-metadata": "10.1.0"
  }
}

Теперь выполним в терминале команду npm run say-hello и увидим результат — сообщение, которое указали в файле package.json:

Скрипт поработал и вернул результат
Скриншот: командная строка Windows / Skillbox Media

Файл package.json

Файл package.json — важнейший элемент проектов в экосистеме Node.js. Мы уже рассмотрели, как можно использовать файл для установки зависимостей, а теперь разберёмся со структурой и другими полезными возможностями.

Структура файла

Содержимое файла package.json записывается в формате JSON, поэтому важно соблюдать требования к его оформлению. Если их проигнорировать, то NPM не сможет прочитать содержимое. Сам файл содержит метаданные проекта, которые задаются с помощью соответствующих разделов:

  • version — текущая версия программы, которая задаётся по правилам семантического версионирования.
"version": "1.0.0"
  • description — краткое описание программы и её возможностей.
"description": "This utility works only with numbers"
  • main — указывает на файл, который будет точкой входа в приложение.
"main": "files/first.js"
  • private — отвечает за возможность публикации приложения в NPM. Модификатор true запрещает публиковать приложение.
"private": true
  • scripts — задаёт список скриптов, которые можно запустить.
"scripts": {
    "say-hello": "echo 'Hello Developer!'"
  }
  • dependencies — список зависимостей, без которых приложение не будет работать.
"dependencies": {
    "express": "^4.17.1",
    "gm": "^1.22.0",
    "lodash": "^4.17.21",
    "music-metadata": "10.1.0"
  }
  • devDependencies — список зависимостей, которые нужны только во время разработки.
"devDependencies": {
  "autoprefixer": "^7.1.2",
  "babel-core": "^6.22.1"
}
  • engines — список версий Node.js, на которых приложение будет работать.
"engines": {
  "node": ">= 5.0.0",
  "npm": ">= 2.5.0",
  "yarn": "^0.14.0"
}
  • browserslist — список браузеров и их версий, в которых приложение будет работать.
"browserslist": {
  "last versions",
  "not ie <= 10"
}
  • license — содержит информацию о лицензии, под которой публикуется код.
"license": "MIT"
  • author — информация об авторе проекта: имя, сайт, электронная почта и другие данные.
{
  "author": {
    "name": "Vasily Popov",
    "email": "v.popov@siteexample.ru",
    "url": "https://v-popov.ru"
  }
}
  • contributors — список людей, которые внесли вклад в развитие проекта.
{
  "contributors": [
    {
      "name": "Vasily Popov",
      "email": "v.popov@siteexample.ru",
      "url": "https://v-popov.ru"
    }
  ]
}
  • bugs — ссылка на баг-трекер проекта.
{
  "bugs": "https://github.com/v_popov/package/issues"
}
  • homepage — ссылка на официальный сайт проекта.
{
  "homepage": "https://v-popov.ru"
}

Версионирование

Во время работы над проектом чаще всего изменяется содержимое разделов dependencies и devDependencies. Разработчики интегрируют новые пакеты и меняют версии уже имеющихся. Для всего этого используется принцип семантического версионирования, а в NPM есть инструменты для удобного упрвления версиями пакетов. С несколькими из них мы уже сталкивались в этой статье, а сейчас посмотрим на всю коллекцию специальных символов.

Для управления версиями пакетов NPM используются следующие символы:

СимволЗначениеПример
~Можно устанавливать только патчи пакета (1.2.x)~1.2.0
^Можно устанавливать только минорные версии и патчи (1.x.x)^1.2.0
*Последняя версия модуля*
>Выше указанной версии>1.2.0
<Ниже указанной версии<1.2.0
=Строго указанная версия модуля=1.2.0
>=Версия, равная указанной или выше>=1.2.0
<=Версия, равная указанной или ниже<=1.2.0
-Диапазон версий1.2.0-1.3.4
latestПоследняя версия модуляlatest
||Логическое ИЛИ<1.2.1 || >1.3.4

Файл package-lock.json

Файл package-lock.json создаётся автоматически при установке NPM-пакетов. Если вы следовали инструкциям выше, то наверняка заметили, что этот файл уже появился в папке проекта. Он нужен для того, чтобы зафиксировать зависимости, которые нужны для работы сторонних пакетов.

Например, программист решил разработать библиотеку для обработки онлайн-платежей. Он решил использовать несколько готовых модулей из NPM и на их основе написал собственное решение.

Спустя какое-то время мы нашли эту библиотеку и решили добавить в свой проект. Информация о ней зафиксируется в уже знакомом нам файле package.json, а зависимости, без которых не будет работать сторонняя библиотека, запишутся в дополнительный файл package-lock.json. Если говорить проще, то в файле package-lock.json описаны зависимости зависимостей.

Если заглянуть в папку node_modules, то там можно найти пакеты, которые вы скачали сами, и случайные модули. Они установились автоматически, потому что нужны для работы библиотек, которые вы используете. Возможным это стало благодаря записям в package-lock.json.

Аддоны в папке node_modules
Скриншот: «Проводник» Windows / Skillbox Media

Что запомнить

  • NPM — удобный менеджер пакетов для тех, кто пишет код на JavaScript.
  • С помощью NPM можно устанавливать библиотеки и модули, которые расширяют возможности языка программирования.
  • Встроенные инструменты управления зависимостями позволяют быстро настраивать окружение проекта и запускать его на сервере или другом компьютере.
  • В NPM предусмотрены удобные функции для автоматического обновления зависимостей до указанных версий.

Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!

Изучайте IT на практике — бесплатно

Курсы за 2990 0 р.

Я не знаю, с чего начать
Научитесь: Профессия Python-разработчик Узнать больше
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована