npm@3: будущее уже здесь

В конце июня была выпущена первая бета третьей версии npm. А 26-го сентября версия 3.3.3 была помечена как latest в официальном репозитории, что знаменует окончание бета тестирования и доступность третьей версии для всех разработчиков. Но переход на третью версию не очень быстрый. К примеру, скачав node.js с официального сайта мы получим в комплекте версию 2.x npm. В данный момент разработчики параллельно поддерживают две версии, 2.x и 3.x — почти как у Python. Надеюсь, с npm переход получится быстрее, разработчики грозятся приурочить его к выходу Node 5. Ну а пока они этого не сделали, я предлагаю вам ознакомиться с нововведениями и узнать как можно одной командой обновить себе npm на тройку.

Одноуровневая структура node_modules


Одной из проблем npm была древовидная организация зависимостей внутри node_modules. На windows это порождало слишком длинные пути к файлам и большая часть программ теряла возможность работать с такими файлами. Плюс дублирование зависимостей: если популярная библиотека использовалась несколькими другими библиотеками, то каждая получала свою копию в своей личной node_modules. Частично это можно было исправить утилитой dedupe, но в ряде случаев npm install обрывался с ошибкой намного раньше, просто потому что на виртуалке заканчивались файловые дескрипторы.

В третьей версии npm большинство зависимостей устанавливается в одну, корневую директорию node_modules. Исключения составят разные версии библиотек: если в процессе изучения зависимостей npm обнаружит, что нужно установить несколько разных версий одной библиотеки, то одна из них будет установлена в корневую директорию node_modules, а остальные — в локальные node_modules.

peerDependencies больше не ставятся автоматически


Среди всех способов указать зависимости, peerDependencies всегда стояло особняком. С помощью этого поля можно было указать “обратную зависимость” для плагинов: с какими версиями библиотеки или утилиты плагин совместим. В случае, если два плагина требовали несовместимой версии библиотки, то npm сообщала об ошибке и прекращал установку. Но был один неприятный момент: если на момент установки плагина библиотека еще не была установлена, то npm автоматически ее устанавливал. Более того, не в директорию node_modules плагина, а на уровень выше. В целом логично, но приводило к неприятным последствиям с неправильными версиями установленных зависимостей. В 3-й версии автоматическую установку убрали и ограничились предупреждающим сообщением. Теперь за наличием библиотеки в списке зависимостей должен следить тот, кто указал в этом списке плагин.

Multi-stage installer


В предыдущей версии скрипты, указанные в таких полях scripts как preinstall и postinstall выполнялись во время установки зависимости. При этом не было гарантии что при выполнении ‘postinstall’ все дочерние зависимости уже будут установлены. Что приводило к большому количеству проблем. В третьей версии установка разделена на шаги:

  1. npm скачивает все зависимости
  2. выполняется скрипт ‘preinstall’ для всех зависимостей
  3. npm устанавливает скачанные зависимости в директорию node_modules (и поддиректории, в случае конфликтов версий).
  4. выполняется скрипт ‘postinstall’ для всех установленных зависимостей.

Это изменение позволило избавиться от большого количества “долгоиграющих” проблем и сделало выполнение скриптов во время инсталляции простым и понятным. Надеюсь.

Мелочи, в ассортименте


Кроме трех крупных изменений, в третьей версии npm есть множество мелких. Это и новое отображение прогресса инсталляции с progress bar, и ключи командной строки --only=/--also=, сделавшие --dev deprecated и много чего по мелочи. Очень рекомендую почитать историю изменение в разделе releases. Там совершенно чумовая девочка community manager которая описывает изменение не просто с огоньком — она жжет напалмом по площадям. Посмотрите, вам понравится.

Чтобы установить последнюю версию npm, достаточно выполнить следующее заклинание командной строки:

npm install -g npm@3

Под OSX могут быть проблемы, если npm было установлено с помощью homebrew. Для такой конфигурации заклинание немного иное:

cd /usr/local/lib/node_modules/npm
npm install -g npm@3


Обновление от 01.11.2015



Как и было обещано, в новом релизе node.js версии 5.0 используется третья версия npm. Теперь — у большинства разработчиков: goo.gl/04k5ny
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 9

    +2
    Из-за нового механизма установки модулей выполнение npm install может занимать в 2 раза больше времени чем раньше. Об этом есть issue на Github, где рассказывается о том, что все оптимизации проделаны, но сделать так же быстро как раньше не получится
      +12
      Одноуровневая структура node_modules
      Боги, наконец-то.
        0
        Может ошибаюсь, но пробовал ставить модули и те зависимости, которые грузятся напрямую с гита (а не с нпм), всё равно остаются древовидными
          0
          Решал эту проблему устанавливая все в одну директорию и потом просто дела ls на нее как на node_modules из всех модулей.
            0
            Ага, только тостер заполонили панические хомячки с вопросами, откуда в node_modules все эти пакеты.
            +1
            Под OSX могут быть проблемы, если npm было установлено с помощью homebrew

            Ни разу проблем не было. Всегда устанавливал так:
            npm install npm@latest -g
            


            Хотя есть один немного неприятный момент с homebrew: при обновлении node.js npm откатывается на 2-ю ветку, и обновлять до 3-й опять приходится руками.
              0
              Именно поэтому написал «могут быть» :). У нас на одном из боксов были проблемы, после обновления npm пропадало из PATH. А на другом боксе такого не было. Закономерность не нашли, но такое вполне гуглится, заклинание выше — один из нагугленных ответов, помогло нам на проблемном боксе.
              0
              А что, per-user установки вместо -g так и нет?
                +1
                $ echo "prefix = $HOME/.npm" >> ~/.npmrc

              Only users with full accounts can post comments. Log in, please.