NPM
NPM — это пакетный менеджер, он управляет зависимостями. Наше приложение зависит от каких-то пакетов, а эти пакеты зависят от других пакетов и т. д.
Изначально NPM создан для NodeJS, но сейчас там очень много всего и для фронтэнда.
Установка
NPM устанавливается вместе с NodeJS. Его так же можно поставить на Мак с помощью brew
или на Линукс с помощью apt
.
При установке глобальных пакетов NPM (например, npm install -g webpack
) могут вылетать EACCES-ошибки. Это связано с недостаточным уровнем доступа вашего пользователя к /usr/local
, куда NPM ставит глобальные пакеты.
Не нужно устанавливать NPM-пакеты под sudo
. Права доступа настраиваются парой команд из официального руководства.
Вообще, стоит отдать предпочтение работе только с локальными пакетами (которые устанавливаются в папку node_modules
внутри проекта). Так у всех разработчиков на проекте будет одна и та же версия. См. ниже "Запуск бинарников локально". Исключения составляют проверялки кода (линтеры) и прочие не зависящие от конкретного проекта пакеты.
Версионирование
NPM использует соглашение semver: MAJOR.MINOR.PATCH
.
При установке пакетов с флагом --save
или --save-dev
в package.json
по-умолчанию записывается его версия с кочергой: ^1.2.3
. Это значит, что при последующих установках NPM будет искать в репозитории пакеты не ниже версии 1.2.3
, но не выше 2.0.0
. То есть все патчи и минорные изменения.
Часто используется ~
. Тильда позволяет устанавливать только патчи. Например, ~1.2.3
даст установить все версии 1.2.x
до 1.3.0
.
Можно установить пакет, жестко прописав его версию: npm install PACKAGE --save --save-exact
. Тогда будет 1.2.3
и при последующих установках поиска обновлений не будет. Однако, наш пакет версии 1.2.3
имеет свой собственный package.json
. И там уже могут быть нечеткие зависимости и с ^
и с ~
.
Для того, чтобы NPM не искал обновления установленных пакетов (при релизе может быть не безопасно) дополнительно генерируется файл package-lock.json
. Его нужно хранить в репозитории.
Соглашения
В наших проектах часто используются следующие NPM-скрипты в package.json
:
npm run dev
— запуск окружения для локальной фронтэнд-разработки. Нет минификации, запускается отдельный сервер для обслуживания ресурсов, все работает максимально быстро.npm run prod
— сборка ресурсов для продадкшена (запускается на CI) или локальной работы с собранными ресурсами, когда не нужно писать стили и JS (для бэкенд-разработки).
Скрипты, которые необходимо запускать в процессе работы с проектом, нужно упомянуть в README.md
.
Запуск бинарников локально
Некоторые пакеты поставляются с утилитами, которые можно запускать из командной строки: gulp
, webpack
и пр. Симлинки на них NPM собирает в папке node_modules/.bin
.
Если такой NPM-пакет упоминается в разделе "scripts"
в package.json
, то NPM будет пытаться его запустить локально, из папки node_modules
, которая находится в проекте. А если он его там не найдет, то попытается найти глобально.
Так, если в package.json
есть, например, скрипт "dev":
"webpack-dev-server --hot"
, то, когда мы пишем в консоли npm run dev
, запускается webpack-dev-server
из папки node_modules
, которая в проекте.
NPM с версии 5.2 поставляется вместе с утилитой npx
, которая предназначена для запуска исполняемых файлов из локально установленных пакетов без создания npm run ...
скриптов. Так npx webpack-dev-server
запустить WDS из node_modules
текущего проекта. Это удобно, если нужно по-быстрому что-то запустить.
Материалы
- Бесплатный курс JS: Настройка окружения
- What everybody should know about npm + слайды — местами устаревший доклад, но пока лучше ничего не нашел.
- Официальная документация NPM
Вопросы для самоконтроля
- Где искать модули?
- Как создать свой скрипт, чтоб запускать его через
npm run myscript
? - Как понять, какой файл в NPM-пакете основной?
- Как установить пакет? Как сохранить его в проекте?
- Зачем нужен файл
package.json
? Зачем нужен файлpackage-lock.json
? - Как посмотреть список устаревших пакетов?
- Как обновить устаревший пакет из проекта?
- Что такое Semver и что значит каждая цифра в номерах версий?
- Как подключить пакет с GitHub? В чем недостаток такого метода и почему его нужно избегать в реальных проектах?