Bower和npm有什么区别?

Games Brainiac 1723 javascript npm bower

bower和之间的根本区别是npm什么?只想要简单明了的东西.我见过我的一些同事在他们的项目中使用bowernpm互换.

Sindre Sorhu.. 1896

所有包管理器都有许多缺点.你只需挑选你可以忍受的东西.

历史

npm开始管理node.js模块(这就是node_modules默认情况下包进入的原因),但是当与Browserify或WebPack 结合使用时,它也适用于前端.

Bower专为前端而设计,并以此为基础进行了优化.

回购的大小

npm远比bower大得多,包括通用JavaScript(如country-data国家信息或sorts可用于前端或后端的排序功能).

鲍尔的包装数量要少得多.

处理款式等

凉亭包括款式等.

npm专注于JavaScript.样式为seperately下载或类似的东西需要npm-sasssass-npm.

依赖性处理

最大的区别是npm执行嵌套依赖项(但默认情况下是平坦的),而Bower需要一个平面依赖树(将依赖项解析的负担放在用户身上).

嵌套依赖树意味着您的依赖项可以拥有自己的依赖项,这些依赖项可以拥有自己的依赖项,依此类推.这允许两个模块需要相同描述的不同版本并且仍然有效.请注意,从npm v3开始,依赖关系树将默认为flat(节省空间),并且只在需要的地方嵌套,例如,如果两个依赖关系需要他们自己的Underscore版本.

有些项目同时使用Bower作为前端软件包,npm用于开发人员工具,如Yeoman,Grunt,Gulp,JSHint,CoffeeScript等.


资源

  • npm 3现在支持平面依赖树. (42认同)
  • "平依赖树"是什么意思?平树是什么 - 列表?那不是一棵树. (37认同)
  • 为什么嵌套的依赖树不能在前端做得那么好? (36认同)
  • 前端npm包也不是一个平面依赖树吗?我正面临着"为什么我们需要2个包管理器?" 困境. (24认同)
  • 实际上,路径也是树.这只是一个特例.来自WikiPedia:"在数学中,更具体地说,在图论中,树是一个无向图,其中任意两个顶点只通过一条路径连接." (14认同)
  • @StevenVachon当然,但很少,所以你不能依赖它.如果你想使用npm进行前端包管理,最好使用`npm dedupe`和browserify. (9认同)
  • 这个答案已经过时了.如果我们使用支持平板依赖的npm 3,你能否更新并告诉我们2016年该怎么做? (6认同)
  • @Danny依赖树是依赖项解析的工作方式,而不是它在磁盘上的布局方式.默认情况下,npm @ 3会尽可能地将依赖项安装为平坦,以便在大多数情况下解决Windows路径限制.Node.js要求逻辑不适用于文件夹名称中的版本.你也许可以通过一些疯狂的符号来获得一些东西,但是在Windows上,符号链接也是微不足道的.你可以在这里阅读更多关于npm @ 3的信息:https://github.com/npm/npm/releases/tag/v3.0.0 (5认同)
  • 作为一个对这些技术一无所知的人,我从谷歌来到这里.我不想听起来令人反感,但我无法理解该死的东西.你为已建立的东西提供太多东西. (5认同)
  • 当我使用最新的npm和节点(2015年12月)时,无论如何我得到了平坦的依赖(当你使用node_modules并且有数百个子文件夹而不是一个时,这是最明显的).那么*现在*有什么区别? (4认同)
  • vasa和@KarelBílek:您将磁盘布局与抽象模型混淆.依赖树以任何方式都不是平坦的,但是NPM3将始终尝试在目录树中尽可能地移动公共依赖项.请参阅Sindre在您之前的评论中给出的链接.向下滚动到"平坦,扁平,平坦!" 在发行说明中了解实际发生的情况. (3认同)
  • 实际上没有人回答@LarsNyström的问题(即使它是在原始答案中):"嵌套依赖树意味着您的依赖关系可以有自己的依赖关系,可以拥有自己的,[i] magine网站必须下载三个jQuery副本".例如库X依赖于jQuery 1.0,库Y依赖于库Y.01,它依赖于jQuery 1.2,库Z依赖于jQuery 2.0.很适合开发,但如果用户必须在浏览器中加载所有三个版本的jQuery,那就不好了. (3认同)

Justus Romij.. 357

这个答案是Sindre Sorhus答案的补充.npm和Bower之间的主要区别在于它们处理递归依赖的方式.请注意,它们可以在一个项目中一起使用.

npm FAQ :( archive.org链接从2015年9月6日)

如果没有嵌套依赖关系,就很难避免依赖冲突.这是npm工作方式的基础,并且已被证明是一种非常成功的方法.

Bower主页上:

Bower针对前端进行了优化.Bower使用平面依赖树,每个包只需要一个版本,从而将页面加载降至最低.

简而言之,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更新:

与Bower相比,npm 3仍然做了不同的事情.它将全局安装依赖项,但仅适用于它遇到的第一个版本.其他版本安装在树中(父模块,然后是node_modules).

  • [node_modules]
    • dep A v1.0
    • dep B v1.0
      • dep A v1.0 (使用root版本)
    • dep C v1.0
      • dep A v2.0(此版本与根版本不同,因此它将是嵌套安装)

有关更多信息,我建议阅读npm 3文档

  • @Shrek我暗中说你实际上可以同时使用它们.正如我在最后一段中所述,它们有不同的用途.这不是我眼中的权衡. (6认同)
  • 现在,"软件开发完全取决于权衡取舍,这几乎是陈词滥调".这是一个很好的例子.必须选择_either_更大的稳定性与`npm` _或_最小资源负载与'bower`. (4认同)
  • @AlexAngas我添加了npm3的更新.与Bower相比,它仍然存在一些重大差异.npm可能总是支持多个版本的依赖项,而Bower则不支持. (4认同)

XML.. 266

TL; DR:日常使用中最大的不同之处不是嵌套依赖...它是模块和全局变量之间的区别.

我认为之前的海报已经涵盖了一些基本的区别.(npm使用嵌套依赖项在管理大型复杂应用程序方面确实非常有用,但我不认为它是最重要的区别.)

然而,我很惊讶没有人明确解释过Bower和npm之间最根本的区别.如果您阅读上面的答案,您会在npm的上下文中看到经常使用的"模块"一词.但随便提到它,好像它甚至只是一种语法差异.

但是模块与全局(或模块与'脚本')的区别可能是Bower和npm之间最重要的区别.将所有东西都放在模块中的npm方法要求你改变你为浏览器编写Javascript的方式,几乎肯定会更好.

凉亭方法:全球资源,与<script>标签一样

在root上,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在当前的背景下.)
  • 当您想要测试单个模块时,您可以非常容易地知道:究竟还有哪些(依赖项)影响模块内部运行的代码?并且,因为您明确地注入了所有内容,所以您可以轻松地模拟这些依赖项.

对我来说,前端代码模块的使用归结为:在更窄的环境中工作,更容易推理和测试,并且对正在发生的事情有更大的确定性.


学习如何使用CommonJS/Node模块语法只需要大约30秒.在给定的JS文件(将成为模块)中,首先声明要使用的任何外部依赖项,如下所示:

var React = require('react');

在文件/模块中,你可以做任何你想做的事情,并创建一些你想要向外部用户公开的对象或函数,或许可以调用它myModule.

在文件末尾,您可以导出要与世界共享的任何内容,如下所示:

module.exports = myModule;

然后,要在浏览器中使用基于CommonJS的工作流,您将使用Browserify之类的工具来获取所有这些单独的模块文件,在运行时封装它们的内容,并根据需要将它们互相注入.

并且,由于ES6模块(您可能会通过Babel或类似程序转换到ES5)正在获得广泛接受,并且在浏览器或Node 4.0中都可以工作,我们也应该提及它们的良好概述.

有关在此平台中使用模块的模式的更多信息.


编辑(2017年2月):Facebook的纱线是当今npm非常重要的潜在替代/补充:快速,确定性,离线包管理,建立在npm为您提供的基础上.值得一看任何JS项目,特别是因为它很容易交换进/出.

  • 很高兴这个答案在这里,其他流行的答案没有提到这个细节.npm迫使你编写模块化代码. (13认同)

Dan Dascales.. 128

2017年10月更新

鲍尔终于被弃用了.故事结局.

较老的答案

来自Spotify的JavaScript开发人员Mattias Petter Johansson:

在几乎所有情况下,使用Browserify和npm over Bower更合适.对于前端应用而言,它只是比Bower更好的打包解决方案.在Spotify,我们使用npm打包整个网络模块(html,css,js),它运行良好.

Bower将自己打造为网络的包管理者.如果这是真的那将是非常棒的 - 作为前端开发人员让我的生活变得更好的包管理器会很棒.问题是Bower没有为此目的提供专门的工具.它没有提供我知道npm没有的工具,特别是对前端开发人员特别有用的工具.前端开发人员使用Bower超过npm没有任何好处.

我们应该停止使用凉亭并在npm周围进行整合.谢天谢地,这就是发生的事情:

模块数量 -  bower vs. npm

使用browserify或webpack,将所有模块连接成大型缩小文件变得非常容易,这对于性能来说非常棒,特别是对于移动设备.Bower不是这样,需要更多的劳动才能获得同样的效果.

npm还使您能够同时使用多个版本的模块.如果你没有做太多的应用程序开发,这可能最初会让你感到害怕,但是一旦你经历了一些依赖性的地狱,你会发现有能力拥有一个模块的多个版本是一个相当不错的很棒的功能.请注意,npm包含一个非常方便的重复数据删除工具,如果您确实需要,它会自动确保您只使用模块的两个版本- 如果两个模块都可以使用相同版本的一个模块,他们会.但如果他们不能,你就会非常方便.

(请注意,截至 2016年8月,Webpack汇总被广泛认为比Browserify更好.)

  • <sarcasm>请记住,即使'hello world'npm项目也需要300多个模块才能运行... </ sarcasm>:O (6认同)
  • @GerardoGrignoli:[亭子是在它的出路(https://github.com/bower/bower/issues/2298#issuecomment-258125059). (4认同)

Sagivf.. 45

Bower维护单个版本的模块,它只会帮助您为您选择正确/最佳的模块.

Javascript依赖管理:npm vs bower vs volo?

NPM对于节点模块更好,因为有一个模块系统,你在本地工作.Bower对浏览器很有用,因为目前只有全局范围,并且您希望对所使用的版本保持高度选择性.

  • @GamesBrainiac你是对的,只是想我用自己的话说. (5认同)
  • 我觉得Sindre在谈到嵌套依赖时提到了这一点. (4认同)
  • @Sagivf如果他们自己没有提供答案,复制其他答案的相关部分*没有错.它只是告诉我一点你说"只是想我用自己的话说." 信贷应该到达应收贷款的地方. (4认同)
  • 我不知道为什么你们这么回答这个答案.在这个答案中确实有新的信息/观点. (2认同)

Nick Heiner.. 33

我的团队离开Bower并迁移到npm因为:

  • 程序化使用很痛苦
  • Bower的界面不断变化
  • 一些功能,如网址速记,完全被打破
  • 在同一个项目中同时使用Bower和npm是很痛苦的
  • 保持bower.json版本字段与git标记同步是痛苦的
  • 源代码管理!=包管理
  • CommonJS支持并不简单

有关详细信息,请参阅"为什么我的团队使用npm而不是bower".


Henry Neo.. 17

http://ng-learn.org/2013/11/Bower-vs-npm/找到了这个有用的解释

一方面,创建了npm来安装node.js环境中使用的模块,或者使用node.js构建的开发工具,例如Karma,lint,minifiers等.npm可以在项目中本地安装模块(默认情况下在node_modules中)或全局安装模块以供多个项目使用.在大型项目中,指定依赖项的方法是创建一个名为package.json的文件,该文件包含依赖项列表.运行npm install时,npm会识别该列表,然后为您下载并安装它们.

另一方面,创建了bower来管理您的前端依赖项.jQuery,AngularJS,下划线等库.与npm类似,它有一个文件,您可以在其中指定一个名为bower.json的依赖项列表.在这种情况下,您的前端依赖项是通过运行bower install来安装的,默认情况下将其安装在名为bower_components的文件夹中.

正如您所看到的,尽管它们执行类似的任务,但它们的目标是一组完全不同的库.


jessopher.. 7

对于使用node.js的许多人来说,bower的一个主要好处是管理非javascript的依赖项.如果他们使用编译为javascript的语言,则可以使用npm来管理他们的一些依赖项.但是,并非所有的依赖项都是node.js模块.编译为javascript的一些可能具有奇怪的源语言特定的修改,使得当用户期望源代码时将它们传递到javascript是一个不优雅的选项.

并非npm包中的所有内容都需要面向用户的javascript,但对于npm库包,至少其中一些应该是.


归档时间:

查看次数:

310106 次

最近记录:

1 年 前