В чем принципиальная разница между bower
и npm
? Просто хочется чего-то простого и понятного. Я видел, как некоторые мои коллеги использовали bower
и npm
как взаимозаменяемые в своих проектах.
В чем разница между Bower и npm?
Ответы (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 и т. Д.
Ресурсы
- Вложенные зависимости - понимание того, почему node_modules работает именно так
npm dedupe
и просматривать, если вы хотите использовать npm для интерфейсного управления пакетами.
- person Sindre Sorhus; 25.01.2014
Этот ответ является дополнением к ответу Синдре Сорхуса. Основное различие между 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.
npm
, либо минимальную нагрузку на ресурсы с bower
.
- person jfmercer; 10.06.2015
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.
Обновление за октябрь 2017 г.
Наконец, Bower была устаревшей. Конец истории.
Старый ответ
От Маттиаса Петтера Йоханссона, разработчика JavaScript в Spotify:
Почти во всех случаях более целесообразно использовать Browserify и npm вместо Bower. Это просто лучшее упаковочное решение для интерфейсных приложений, чем Bower. В Spotify мы используем npm для упаковки целых веб-модулей (html, css, js), и это работает очень хорошо.
Bower позиционирует себя как менеджер пакетов для Интернета. Было бы здорово, если бы это было правдой - менеджер пакетов, который сделал бы мою жизнь лучше как фронтенд-разработчика, был бы потрясающим. Проблема в том, что Bower не предлагает специальных инструментов для этой цели. Он не предлагает НИКАКИХ инструментов, о которых я знаю, чего нет в npm, и особенно ничего, что было бы особенно полезно для интерфейсных разработчиков. Интерфейсному разработчику просто не выгодно использовать Bower по сравнению с npm.
Мы должны прекратить использовать bower и консолидироваться около npm. К счастью, вот что происходит :
С помощью browserify или webpack становится очень легко объединить все ваши модули в большие минифицированные файлы, что обеспечивает отличную производительность, особенно для мобильных устройств. Иначе обстоит дело с Bower, для получения такого же эффекта потребуется значительно больше усилий.
npm также предлагает вам возможность использовать несколько версий модулей одновременно. Если вы не занимались большой разработкой приложений, это может сначала показаться вам плохим, но как только вы пройдете несколько приступов Ад зависимостей, вы поймете, что возможность иметь несколько версий одного модуля - чертовски замечательная функция. Обратите внимание, что npm включает очень удобный инструмент дедупликации, который автоматически гарантирует, что вы используете только две версии module, если у вас действительно есть - если два модуля могут использовать одну и ту же версию одного модуля, они будут. Но если они не могут, у вас есть очень полезная вещь.
(Обратите внимание, что Webpack и rollup, по мнению многих, лучше, чем Browserify по состоянию на август 2016 г.)
Bower поддерживает единственную версию модулей, она только пытается помочь вам выбрать правильный / лучший для вас.
Управление зависимостями Javascript: npm vs bower vs volo? а>
NPM лучше подходит для узловых модулей, потому что есть модульная система и вы работаете локально. Bower хорош для браузера, потому что в настоящее время существует только глобальная область видимости, и вы хотите очень избирательно подходить к версии, с которой вы работаете.
Моя команда ушла из Bower и перешла на npm, потому что:
- Программное использование было болезненным
- Интерфейс Бауэра постоянно менялся
- Некоторые функции, например сокращение URL-адреса, полностью не работают.
- Использование Bower и npm в одном проекте болезненно
- Синхронизировать поле версии bower.json с тегами git - это больно
- Контроль версий! = Управление пакетами
- Поддержка CommonJS не проста
Для получения дополнительной информации см. «Почему моя команда использует npm вместо bower».
Нашел это полезное объяснение на сайте 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.
Как видите, хотя они выполняют схожую задачу, они нацелены на совсем другой набор библиотек.
npm dedupe
это немного устарело. См. ответ Маттиаса.
- person Dan Dascalescu; 04.07.2015
Для многих людей, работающих с node.js, основным преимуществом bower является управление зависимостями, которые вообще не являются javascript. Если они работают с языками, которые компилируются в javascript, npm можно использовать для управления некоторыми их зависимостями. однако не все их зависимости будут модулями node.js. Некоторые из тех, которые компилируются в javascript, могут иметь странные специфические для исходного языка искажения, что делает их передачу скомпилированными в javascript неэлегантным вариантом, когда пользователи ожидают исходный код.
Не все в пакете npm должно быть ориентировано на пользователя javascript, но для пакетов библиотеки npm, по крайней мере, некоторые из них должны быть.