В чем разница между бауэром и нпм?

1580

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

  • 7
    Связанный ответ stackoverflow.com/a/21199026/1310070
  • 4
    возможный дубликат управления зависимостями Javascript: npm против bower против volo?
Показать ещё 2 комментария
Теги:
npm
bower

8 ответов

1644
Лучший ответ

npm чаще всего используется для управления модулями Node.js, но он также работает для интерфейсного модуля в сочетании с Browserify и/или $ npm dedupe.

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

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

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

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


Ресурсы

  • 36
    Почему вложенное дерево зависимостей не работает так хорошо на внешнем интерфейсе?
  • 24
    Может ли внешний пакет npm также не быть плоским деревом зависимостей? Я сталкиваюсь с вопросом "зачем нам 2 менеджера пакетов?" дилемма.
Показать ещё 12 комментариев
300

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

В часто задаваемых вопросах npm:

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

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

Bower оптимизирован для front-end. Бауэр использует плоскую зависимость дерево, требующее только одной версии для каждого пакета, уменьшая загрузку страницы до минимума.

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

НПМ:

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 для пакетов, которые вы хотите публиковать на своих веб-страницах (например, время выполнения, где вы избегаете дублирования), и использовать npm для других вещей, таких как тестирование, построение, оптимизация, проверка и т.д. ( например, время разработки, где дублирование вызывает меньшую озабоченность).

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

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

  • [node_modules]
    • dep A v1.0
    • dep B v1.0
      • dep A v1.0 (использует корневую версию)
    • dep C v1.0
      • dep A v2.0 (эта версия отличается от корневой версии, поэтому она будет вложенной установкой)

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

  • 4
    Это почти клише, когда «разработка программного обеспечения - это компромиссы». Это хороший пример. Нужно выбрать либо большую стабильность с npm либо минимальную загрузку ресурсов с помощью bower .
  • 6
    @ Шрек Я безоговорочно заявляю, что вы на самом деле можете использовать оба. У них разные цели, как я утверждаю в последнем абзаце. Это не компромисс в моих глазах.
Показать ещё 3 комментария
227

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

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

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

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

Подход Bower: глобальные ресурсы, например <script> Теги

В корневом режиме Bower загружает файлы с обычным файлом script. Независимо от того, какие файлы script содержат, Bower загрузит их. Что в основном означает, что Bower так же, как и все ваши сценарии в обычном <script> в <head> вашего HTML.

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

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

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

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

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

Умнее людей, чем я занялся вопросом "Почему модули?", но здесь сводка капсул:

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

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


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

var React = require('react');

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

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

module.exports = myModule;

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

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

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


EDIT (февраль 2017): Facebook Yarn - очень важная потенциальная замена/дополнение для npm в эти дни: быстрое, детерминированное, офлайн управление пакетами, основанное на том, что дает вам npm. Это стоит посмотреть на любой проект JS, особенно потому, что его легко можно менять в/из.

  • 13
    Рад, что этот ответ был здесь, другие популярные ответы не упоминают эту деталь. npm заставляет вас писать модульный код.
  • 0
    Я извиняюсь от людей, которые очень мало заботятся обо всех размышлениях в парфе javascript, но так происходит, что у них есть бизнес, использующий небольшое веб-приложение. Недавно был вынужден попробовать npm от использования bower с инструментарием, который мы используем для разработки чертовой вещи. Я могу сказать вам, что самая большая разница в времени ожидания, npm занимает много времени. Помните, что компиляция мультфильма xkcd с парнями, играющими в мечах, выкрикивая «компиляцию» своему боссу; это в значительной степени то, что npm добавил к беседке.
91

Обновление 2017-Oct

Bower наконец-то был устарел. Конец истории.

Более старый ответ

От Mattias Petter Johansson, разработчика JavaScript в Spotify:

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

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

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

Изображение 2136

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

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

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

  • 1
    вебпак и нпм еще лучше я думаю ..
  • 6
    <sarcasm> Пожалуйста, имейте в виду, что даже для проекта npm 'hello world' требуется более 300 модулей для запуска ... </ sarcasm>: O
Показать ещё 3 комментария
40

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

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

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

  • 4
    Я чувствую, что Синдре упоминает об этом, когда говорит о вложенной зависимости.
  • 5
    @GamesBrainiac, ты прав, просто подумал, что я бы сказал это своими словами.
Показать ещё 5 комментариев
30

Моя команда отошла от Бауэра и переместилась на галлон, потому что:

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

Подробнее см. "Почему моя команда использует npm вместо bower" .

13

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

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

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

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

  • 1
    С появлением npm dedupe это немного устарело. Смотрите ответ Маттиаса .
4

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

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

  • 0
    В этом посте npmjs говорится: «Ваш пакет может содержать что угодно, будь то ES6, JS на стороне клиента или даже HTML и CSS. Это вещи, которые естественным образом появляются вместе с JavaScript, поэтому поместите их туда».
  • 1
    Существует разница между может содержать и должен включать . Конечно, они могут содержать все что угодно, но в целом они должны включать в себя какой-то интерфейс к commonJS. В конце концов, это «менеджер пакетов узлов». Часть об этих вещах, которые естественно появляются вместе с Javascript , важна. Есть много вещей, которые тангенциально связаны с javascript, которые не появляются рядом с ним.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню