В чем разница между Bower и npm?

В чем принципиальная разница между bower и npm? Просто хочется чего-то простого и понятного. Я видел, как некоторые мои коллеги использовали bower и npm как взаимозаменяемые в своих проектах.


person Games Brainiac    schedule 05.09.2013    source источник
comment
Связанный ответ stackoverflow.com/a/21199026/1310070   -  person sachinjain024    schedule 19.03.2014
comment
возможный дубликат Управление зависимостями Javascript: npm vs bower vs volo?   -  person anotherdave    schedule 24.07.2014
comment
Ответ на этот вопрос кажется устаревшим. Может ли кто-нибудь сказать нам, что делать в 2016 году, если мы будем использовать npm 3, поддерживающий плоскую зависимость? В чем разница wince npm3 и bower и что лучше всего делать прямо сейчас?   -  person amdev    schedule 05.10.2016
comment
В итоге, @amdev: bower устарела. npm (или Yarn, разница лишь незначительная) - вот где он находится. Я не знаю реальных альтернатив.   -  person XML    schedule 07.01.2018


Ответы (8)


У всех менеджеров пакетов есть много недостатков. Вам просто нужно выбрать, с чем вы сможете жить.

История

npm начал с управления модулями node.js (поэтому пакеты по умолчанию попадают в node_modules), но он работает на переднем плане. -end также в сочетании с Browserify или веб-пакет.

Bower создан исключительно для внешнего интерфейса и оптимизирован с учетом этого.

Размер репо

npm намного больше, чем bower, включая JavaScript общего назначения (например, country-data для информации о стране или sorts для функций сортировки, которые можно использовать на передней или задней стороне).

У Bower гораздо меньше пакетов.

Обработка стилей и т. Д.

Bower включает стили и т. Д.

npm ориентирован на JavaScript. Стили загружаются отдельно или требуются для чего-то вроде npm-sass или sass-npm.

Обработка зависимостей

Самая большая разница в том, что npm выполняет вложенные зависимости (но по умолчанию является плоским), в то время как Bower требует плоского дерева зависимостей (возлагает бремя разрешения зависимостей на пользователя).

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

Некоторые проекты используют и то, и другое: они используют Bower для интерфейсных пакетов и npm для инструментов разработчика, таких как Yeoman, Grunt, Gulp, JSHint, CoffeeScript и т. Д.


Ресурсы

person Sindre Sorhus    schedule 06.09.2013
comment
Почему вложенное дерево зависимостей не справляется с этой задачей во внешнем интерфейсе? - person Lars Nyström; 19.01.2014
comment
Может ли интерфейсный пакет npm не быть плоским деревом зависимостей? Я столкнулся с вопросом, зачем нам 2 менеджера пакетов? дилемма. - person Steven Vachon; 24.01.2014
comment
@StevenVachon, конечно, но их очень мало, так что на это нельзя полагаться. Лучше использовать npm dedupe и просматривать, если вы хотите использовать npm для интерфейсного управления пакетами. - person Sindre Sorhus; 25.01.2014
comment
Что вы имеете в виду под плоским деревом зависимостей? Плоское дерево это что - список? Значит, это не дерево. - person mvmn; 17.10.2014
comment
Собственно, путь - это тоже дерево. Это просто особый случай. Из WikiPedia: В математике, а точнее в теории графов, дерево - это неориентированный граф, в котором любые две вершины соединены ровно одним путем. - person Jørgen Fogh; 25.12.2014
comment
Я до сих пор не понимаю, почему я предпочитаю использовать дерево вместо того, чтобы держать вещи плоскими. Почему бы вам не иметь возможность иметь несколько версий определенных пакетов со сглаженными зависимостями? Не могли бы вы просто включить в имена зависимостей номера версий? Дерево кажется слишком сложным, особенно с учетом ограничений пути в Windows. И npm dedupe, судя по тому, что я с ним недолго играл, кажется полон проблем. - person Danny; 30.07.2015
comment
@Danny Дерево зависимостей - это то, как работает разрешение зависимостей, а не то, как оно расположено на диске. npm @ 3 будет устанавливать зависимости как можно более плоскими по умолчанию, чтобы в большинстве случаев обойти ограничения пути Windows. Логика Node.js require не будет работать с версией в именах папок. Возможно, вы могли бы получить что-то работающее с каким-то сумасшедшим символическим связыванием, но символические ссылки тоже не подходят для Windows. Вы можете узнать больше о npm @ 3 здесь: github.com/npm/npm/ релизы / тег / v3.0.0 - person Sindre Sorhus; 31.07.2015
comment
npm 3 теперь поддерживает плоское дерево зависимостей. - person vasa; 21.11.2015
comment
Когда я использую новейшие npm и node (в декабре 2015 года), у меня все равно была плоская зависимость (это наиболее очевидно, когда вы node_modules и получаете сотни подпапок вместо одной). Так в чем же разница сейчас? - person Karel Bílek; 24.12.2015
comment
vasa и @ KarelBílek: Вы путаете структуру диска с абстрактной моделью. Дерево зависимостей ни в коем случае не является плоским, но NPM3 всегда будет пытаться переместить общие зависимости как можно дальше вверх по дереву каталогов. См. Ссылку в комментариях Синдре непосредственно перед вашей. Прокрутите вниз до Плоский, плоский, плоский! в примечаниях к выпуску, чтобы понять, что на самом деле происходит. - person oligofren; 10.02.2016
comment
Никто на самом деле не ответил на вопрос @ LarsNyström (хотя он был в исходном ответе): вложенное дерево зависимостей означает, что ваши зависимости могут иметь свои собственные зависимости, [i] представьте, что сайт должен загрузить три копии jQuery. например библиотека X зависит от jQuery 1.0, библиотека Y зависит от библиотеки Y.01, которая зависит от jQuery 1.2, библиотека Z зависит от jQuery 2.0. Прекрасно для разработки, но не годится, если пользователю нужно загрузить все три версии jQuery в своем браузере. - person mummybot; 25.02.2016
comment
как человек, ничего не знающий об этих технологиях, я пришел сюда из Google. Не хочу показаться оскорбительным, но я ни черта не мог понять. Вы слишком много отдаете за установленное. - person Stefano Borini; 13.05.2016
comment
@SindreSorhus: Вы, кажется, написали что-то о npm, что вас не устраивает. NOM предназначен не только для узла, он предназначен для установки всех плагинов, фреймворков, приложений и библиотек. - person Jasmine; 02.08.2016
comment
Этот ответ устарел. Можете ли вы обновить и сообщить нам, что делать в 2016 году, если мы будем использовать npm 3, который поддерживает плоскую зависимость? - person amdev; 05.10.2016

Этот ответ является дополнением к ответу Синдре Сорхуса. Основное различие между npm и Bower заключается в том, как они обрабатывают рекурсивные зависимости. Обратите внимание, что их можно использовать вместе в одном проекте.

На npm FAQ: (ссылка на archive.org от 6 сентября 2015 г.)

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

На главной странице Bower:

Bower оптимизирован для внешнего интерфейса. Bower использует плоское дерево зависимостей, требуя только одну версию для каждого пакета, что снижает нагрузку на страницу до минимума.

Короче говоря, npm стремится к стабильности. Bower стремится к минимальной ресурсной нагрузке. Если вы нарисуете структуру зависимостей, вы увидите следующее:

npm:

project root
[node_modules] // default directory for dependencies
 -> dependency A
 -> dependency B
    [node_modules]
    -> dependency A

 -> dependency C
    [node_modules]
    -> dependency B
      [node_modules]
       -> dependency A 
    -> dependency D

Как видите, он рекурсивно устанавливает некоторые зависимости. У зависимости A три установленных экземпляра!

Бауэр:

project root
[bower_components] // default directory for dependencies
 -> dependency A
 -> dependency B // needs A
 -> dependency C // needs B and D
 -> dependency D

Здесь вы видите, что все уникальные зависимости находятся на одном уровне.

Итак, зачем использовать npm?

Возможно, для зависимости B требуется другая версия зависимости A, чем для зависимости C. npm устанавливает обе версии этой зависимости, поэтому она все равно будет работать, но Bower вызовет конфликт, потому что не любит дублирование (потому что загрузка тот же ресурс на веб-странице очень неэффективен и дорог, а также может давать серьезные ошибки). Вам придется вручную выбрать, какую версию вы хотите установить. Это может привести к тому, что одна из зависимостей сломается, но это то, что вам все равно нужно будет исправить.

Итак, Bower обычно используется для пакетов, которые вы хотите опубликовать на своих веб-страницах (например, runtime, где вы избегаете дублирования), и использовать npm для других вещей, таких как тестирование, сборка, оптимизация, проверка и т. д. (например, время разработки, где дублирование менее важно).

Обновление для npm 3:

npm 3 по-прежнему работает иначе, чем Bower. Он установит зависимости глобально, но только для первой обнаруженной версии. Остальные версии устанавливаются в дереве (родительский модуль, затем node_modules).

  • [node_modules]
    • dep A v1.0
    • dep B v1.0
      • dep A v1.0 (uses root version)
    • dep C v1.0
      • dep A v2.0 (this version is different from the root version, so it will be an nested installation)

Для получения дополнительной информации я предлагаю прочитать документы npm 3.

person Justus Romijn    schedule 24.11.2014
comment
То, что разработка программного обеспечения - это компромисс, стало почти клише. Это хороший пример. Необходимо выбрать либо большую стабильность с npm , либо минимальную нагрузку на ресурсы с bower. - person jfmercer; 10.06.2015
comment
@Shrek Я неявно заявляю, что вы действительно можете использовать и то, и другое. У них разные цели, как я заявляю в последнем абзаце. На мой взгляд, это не компромисс. - person Justus Romijn; 10.06.2015
comment
Ах, я вижу, я тебя неправильно понял. Или я недостаточно внимательно прочитал. Спасибо за разъяснения. :-) Хорошо, что и то и другое можно использовать без компромиссов. - person jfmercer; 10.06.2015
comment
@AlexAngas Я добавил обновление для npm3. Он все еще имеет некоторые существенные отличия от Bower. npm, вероятно, всегда будет поддерживать несколько версий зависимостей, а Bower - нет. - person Justus Romijn; 18.01.2016
comment
npm 3 приближается к беседке;) - person ni3; 21.03.2017

TL; DR: самая большая разница в повседневном использовании - это не вложенные зависимости ... это разница между модулями и глобальными объектами.

Я думаю, что предыдущие плакаты хорошо освещали некоторые из основных различий. (Использование вложенных зависимостей в npm действительно очень полезно при управлении большими и сложными приложениями, хотя я не думаю, что это самое важное различие.)

Однако я удивлен, что никто не объяснил явно одно из самых фундаментальных различий между Bower и npm. Если вы прочитаете ответы выше, вы увидите, что слово «модули» часто используется в контексте npm. Но это упомянуто случайно, как будто это может быть просто синтаксическая разница.

Но это различие между модулями и глобальными объектами (или модулями и «скриптами»), возможно, является наиболее важным различием между Bower и npm. Подход npm, заключающийся в размещении всего в модулях, требует, чтобы вы изменили способ написания Javascript для браузера, почти наверняка к лучшему.

Подход Бауэра: глобальные ресурсы, Like <script> Tags

По сути, Bower занимается загрузкой старых файлов сценариев. Что бы ни содержали эти файлы сценариев, Бауэр загрузит их. По сути, это означает, что Bower - это то же самое, что включать все ваши скрипты из простых <script> в <head> вашего HTML.

Итак, тот же базовый подход, к которому вы привыкли, но при этом вы получаете удобство автоматизации:

  • Раньше вам нужно было включать зависимости JS в репозиторий вашего проекта (во время разработки) или получать их через CDN. Теперь вы можете пропустить этот дополнительный вес загрузки в репо, и кто-то может быстро bower install получить то, что ему нужно, локально.
  • Если зависимость Bower затем указывает свои собственные зависимости в своем bower.json, они также будут загружены для вас.

Но помимо этого Bower не меняет способ написания javascript. Ничего из того, что находится внутри файлов, загружаемых Bower, вообще не нужно менять. В частности, это означает, что ресурсы, предоставляемые в скриптах, загружаемых Bower, будут (обычно, но не всегда) по-прежнему определяться как глобальные переменные, доступные из любого места в контексте выполнения браузера.

Подход npm: общие модули JS, явное внедрение зависимостей

Весь код в области Node (и, следовательно, весь код, загружаемый через npm) структурирован как модули (в частности, как реализация Формат модуля CommonJS, или теперь как модуль ES6). Итак, если вы используете NPM для обработки зависимостей на стороне браузера (через Browserify или что-то еще, что выполняет ту же работу), вы структурируете свой код так же, как это делает Node.

Более умные люди, чем я, взялись за вопрос «Почему именно модули?», Но вот краткое изложение:

  • Все внутри модуля эффективно пространством имен, что означает, что это больше не глобальная переменная, и вы не можете случайно ссылаться на нее без намерения.
  • Все, что находится внутри модуля, должно быть намеренно введено в конкретный контекст (обычно другой модуль), чтобы его можно было использовать.
  • Это означает, что у вас может быть несколько версий одной и той же внешней зависимости (скажем, lodash) в разных частях вашего приложения, и они не будут конфликтовать / конфликтовать. (Это случается на удивление часто, потому что ваш собственный код хочет использовать одну версию зависимости, но одна из ваших внешних зависимостей указывает другую, которая конфликтует. Или у вас есть две внешние зависимости, каждой из которых нужна другая версия.)
  • Поскольку все зависимости вручную вводятся в конкретный модуль, их очень легко рассуждать. Вы знаете наверняка: Единственный код, который мне нужно учитывать при работе над этим, - это то, что я намеренно выбрал для внедрения здесь.
  • Поскольку даже содержимое внедренных модулей инкапсулируется за переменной, которой вы его назначаете, и весь код выполняется в ограниченной области, неожиданности и коллизии становятся очень маловероятными. Гораздо, гораздо менее вероятно, что что-то из одной из ваших зависимостей случайно переопределит глобальную переменную без вашего осознания или что вы это сделаете. (Это может случиться, но обычно для этого нужно изо всех сил стараться изо всех сил, используя что-то вроде window.variable. Единственная авария, которая все еще имеет тенденцию происходить, - это присвоение this.variable, не осознавая, что this на самом деле window в текущем контексте.)
  • Когда вы хотите протестировать отдельный модуль, вы можете очень легко узнать: что именно (зависимости) влияет на код, выполняемый внутри модуля? И, поскольку вы явно вводите все, вы можете легко имитировать эти зависимости.

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


Чтобы научиться использовать синтаксис модуля CommonJS / Node, требуется всего около 30 секунд. Внутри данного JS-файла, который будет модулем, вы сначала объявляете любые внешние зависимости, которые хотите использовать, например:

var React = require('react');

Внутри файла / модуля вы делаете то, что обычно делаете, и создаете объект или функцию, которые хотите предоставить внешним пользователям, возможно, называя это myModule.

В конце файла вы экспортируете все, чем хотите поделиться с миром, например:

module.exports = myModule;

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

И, поскольку модули ES6 (которые вы, вероятно, перенесете в ES5 с помощью Babel или аналогичных) получают широкое признание и работают как в браузере, так и в Node 4.0, мы должны упомянуть хороший обзор и их.

Подробнее о шаблонах для работы с модулями в этой колоде.


РЕДАКТИРОВАТЬ (февраль 2017 г.): Yarn от Facebook в наши дни является очень важной потенциальной заменой / дополнением для npm: быстрый, детерминированный, автономный пакет -управление, основанное на том, что дает вам npm. Стоит взглянуть на любой JS-проект, тем более, что его очень легко поменять местами.


РЕДАКТИРОВАТЬ (май 2019 г.) Bower, наконец, устарела . Конец истории. (h / t: @DanDascalescu, ниже, для краткого резюме.)

И хотя Yarn все еще активен, большая часть импульса для него вернулась к npm. однажды он перенял некоторые ключевые особенности Yarn.

person XML    schedule 26.07.2015
comment
Рад, что этот ответ был здесь, в других популярных ответах эта деталь не упоминается. npm заставляет вас писать модульный код. - person Juan Mendes; 13.05.2016
comment
Прошу прощения, от людей, которые очень мало заботятся обо всей фаззинге в javascript parlands, но так уж случилось, что он управляет бизнесом, который использует небольшое веб-приложение. Недавно был вынужден попробовать npm из-за использования bower с набором инструментов, который мы используем для разработки чертовски веб-вещей. Я могу вам сказать, что самая большая разница - это время ожидания, npm занимает много времени. Помните, что это сборка мультфильма xkcd с парнями, играющими на мечах и кричащими «компилирование» своему боссу; это в значительной степени то, что npm добавила в беседку. - person Pedro Rodrigues; 22.11.2018

Обновление за октябрь 2017 г.

Наконец, Bower была устаревшей. Конец истории.

Старый ответ

От Маттиаса Петтера Йоханссона, разработчика JavaScript в Spotify:

Почти во всех случаях более целесообразно использовать Browserify и npm вместо Bower. Это просто лучшее упаковочное решение для интерфейсных приложений, чем Bower. В Spotify мы используем npm для упаковки целых веб-модулей (html, css, js), и это работает очень хорошо.

Bower позиционирует себя как менеджер пакетов для Интернета. Было бы здорово, если бы это было правдой - менеджер пакетов, который сделал бы мою жизнь лучше как фронтенд-разработчика, был бы потрясающим. Проблема в том, что Bower не предлагает специальных инструментов для этой цели. Он не предлагает НИКАКИХ инструментов, о которых я знаю, чего нет в npm, и особенно ничего, что было бы особенно полезно для интерфейсных разработчиков. Интерфейсному разработчику просто не выгодно использовать Bower по сравнению с npm.

Мы должны прекратить использовать bower и консолидироваться около npm. К счастью, вот что происходит :

Количество модулей - bower vs. npm

С помощью browserify или webpack становится очень легко объединить все ваши модули в большие минифицированные файлы, что обеспечивает отличную производительность, особенно для мобильных устройств. Иначе обстоит дело с Bower, для получения такого же эффекта потребуется значительно больше усилий.

npm также предлагает вам возможность использовать несколько версий модулей одновременно. Если вы не занимались большой разработкой приложений, это может сначала показаться вам плохим, но как только вы пройдете несколько приступов Ад зависимостей, вы поймете, что возможность иметь несколько версий одного модуля - чертовски замечательная функция. Обратите внимание, что npm включает очень удобный инструмент дедупликации, который автоматически гарантирует, что вы используете только две версии module, если у вас действительно есть - если два модуля могут использовать одну и ту же версию одного модуля, они будут. Но если они не могут, у вас есть очень полезная вещь.

(Обратите внимание, что Webpack и rollup, по мнению многих, лучше, чем Browserify по состоянию на август 2016 г.)

person Dan Dascalescu    schedule 04.07.2015
comment
‹Sarcasm› Пожалуйста, имейте в виду, что даже проекту npm 'hello world' требуется более 300 модулей для запуска ... ‹/sarcasm›: O - person Mariusz Jamro; 11.12.2016
comment
Я не согласен с тем, что большие минифицированные файлы хороши для производительности, особенно для мобильных устройств. Скорее наоборот: ограниченная пропускная способность требует небольших файлов, загружаемых по запросу. - person Michael Franzl; 09.04.2017
comment
Не очень хороший совет. Большинство пакетов npm - это только серверная часть nodejs. Если вы не используете javascript на бэкэнде или у вас нет модульной системы, количество пакетов не имеет значения, потому что Bower будет намного лучше соответствовать вашим потребностям. - person Gerardo Grignoli; 11.04.2017
comment
@GerardoGrignoli: Бауэр выходит. - person Dan Dascalescu; 12.04.2017

Bower поддерживает единственную версию модулей, она только пытается помочь вам выбрать правильный / лучший для вас.

Управление зависимостями Javascript: npm vs bower vs volo?

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

person Sagivf    schedule 19.07.2014
comment
Я чувствую, что Синдре упоминает это, когда говорит о вложенной зависимости. - person Games Brainiac; 20.07.2014
comment
@GamesBrainiac, ты прав, просто подумал, что перескажу своими словами. - person Sagivf; 20.07.2014
comment
@dayuloli, это был мой первый пост о stackoverflow, и я не понимал, что авторские права так важны. Мне понравился ответ на этот вопрос, поэтому я его использовал. Я изменил сообщение. Когда я сказал свои слова, я даже не вспомнил, что взял их откуда-то еще. - person Sagivf; 04.03.2015
comment
@Sagivf Нет ничего плохого в копировании ** соответствующих частей других ответов, если они сами не предоставили здесь ответ. Это меня немного беспокоило, ты сказал, просто подумал, что я изложу это своими словами. Кредит должен поступать туда, где причитается. - person dayuloli; 04.03.2015
comment
Я не знаю, почему вы так сильно выбрали этот ответ. В этом ответе мне действительно есть новая информация / перспектива. - person Calvin; 01.12.2015

Моя команда ушла из Bower и перешла на npm, потому что:

  • Программное использование было болезненным
  • Интерфейс Бауэра постоянно менялся
  • Некоторые функции, например сокращение URL-адреса, полностью не работают.
  • Использование Bower и npm в одном проекте болезненно
  • Синхронизировать поле версии bower.json с тегами git - это больно
  • Контроль версий! = Управление пакетами
  • Поддержка CommonJS не проста

Для получения дополнительной информации см. «Почему моя команда использует npm вместо bower».

person Nick Heiner    schedule 16.02.2015

Нашел это полезное объяснение на сайте http://ng-learn.org/2013/11/Bower-vs-npm/

С одной стороны, npm был создан для установки модулей, используемых в среде node.js, или инструментов разработки, созданных с использованием node.js, таких как Karma, lint, minifiers и т. Д. npm может устанавливать модули локально в проекте (по умолчанию в node_modules) или глобально для использования в нескольких проектах. В больших проектах можно указать зависимости путем создания файла с именем package.json, который содержит список зависимостей. Этот список распознается npm, когда вы запускаете npm install, которая затем загружает и устанавливает их для вас.

С другой стороны, bower был создан для управления зависимостями вашего внешнего интерфейса. Такие библиотеки, как jQuery, AngularJS, подчеркивание и т. Д. Подобно npm, у него есть файл, в котором вы можете указать список зависимостей, который называется bower.json. В этом случае зависимости вашего внешнего интерфейса устанавливаются путем запуска bower install, который по умолчанию устанавливает их в папку с именем bower_components.

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

person Henry Neo    schedule 03.10.2014
comment
С появлением npm dedupe это немного устарело. См. ответ Маттиаса. - person Dan Dascalescu; 04.07.2015

Для многих людей, работающих с node.js, основным преимуществом bower является управление зависимостями, которые вообще не являются javascript. Если они работают с языками, которые компилируются в javascript, npm можно использовать для управления некоторыми их зависимостями. однако не все их зависимости будут модулями node.js. Некоторые из тех, которые компилируются в javascript, могут иметь странные специфические для исходного языка искажения, что делает их передачу скомпилированными в javascript неэлегантным вариантом, когда пользователи ожидают исходный код.

Не все в пакете npm должно быть ориентировано на пользователя javascript, но для пакетов библиотеки npm, по крайней мере, некоторые из них должны быть.

person jessopher    schedule 11.10.2014
comment
В этом сообщении блога npmjs говорится, что ваш пакет может содержать что угодно , будь то ES6, клиентский JS или даже HTML и CSS. Это вещи, которые естественным образом появляются вместе с JavaScript, так что поместите их туда ... - person Dan Dascalescu; 04.07.2015
comment
Есть разница между может содержать и должен включать. Конечно, они могут содержать что угодно, но в целом они должны включать какой-то интерфейс для commonJS. В конце концов, это «менеджер пакетов узлов». Часть о Это вещи, которые естественно появляются вместе с Javascript, очень важна. Есть много вещей, косвенно связанных с javascript, которые не естественно появляются рядом. - person jessopher; 09.12.2015