bower和npm的根本区别是什么?只想要简单明了的东西。我见过我的一些同事在他们的项目中交替使用bower和npm。
当前回答
TL;DR:日常使用中最大的区别不是嵌套依赖关系。。。这是模块和全局变量之间的区别。
我认为之前的海报很好地涵盖了一些基本的区别。(npm对嵌套依赖的使用确实非常有助于管理大型、复杂的应用程序,尽管我认为这不是最重要的区别。)
然而,我很惊讶,没有人明确解释鲍尔和npm之间最根本的区别之一。如果你阅读上面的答案,你会看到npm上下文中经常使用的单词“modules”。但这是随便提及的,好像它甚至可能只是语法上的差异。
但模块与全局(或模块与“脚本”)的区别可能是Bower和npm之间最重要的区别。将所有内容放入模块的npm方法要求您改变为浏览器编写Javascript的方式,几乎可以肯定是为了更好。
Bower方法:全球资源,如<script>标签
在根目录中,Bower负责加载普通的旧脚本文件。无论这些脚本文件包含什么,Bower都会加载它们。这基本上意味着Bower就像将所有脚本都包含在HTML的<head>中。
所以,这是您习惯的基本方法,但您可以获得一些很好的自动化便利:
您过去需要在项目库中包含JS依赖项(在开发时),或者通过CDN获取它们。现在,你可以跳过回购中的额外下载重量,有人可以快速安装bower,并立即在本地获得他们需要的内容。如果Bower依赖项随后在其Bower.json中指定了自己的依赖项,那么也会为您下载这些依赖项。
但除此之外,鲍尔并没有改变我们编写javascript的方式。Bower加载的文件中的内容根本不需要更改。特别是,这意味着Bower加载的脚本中提供的资源(通常,但不总是)仍然被定义为全局变量,可以从浏览器执行上下文中的任何位置获得。
npm方法:公共JS模块、显式依赖注入
Node land中的所有代码(以及通过npm加载的所有代码)都被构造为模块(具体来说,作为CommonJS模块格式的实现,或者现在作为ES6模块)。因此,如果您使用NPM来处理浏览器端的依赖关系(通过Browserify或其他执行相同任务的工具),那么您将以Node的方式构造代码。
比我更聪明的人解决了“为什么选择模块?”的问题,但这里有一个胶囊摘要:
模块中的任何内容都是有效的名称空间,这意味着它不再是一个全局变量,您不能无意中引用它。模块内的任何内容都必须有意地注入到特定上下文(通常是另一个模块)中,以便利用它这意味着您可以在应用程序的不同部分拥有相同外部依赖项(比如lodash)的多个版本,并且它们不会发生冲突。(这种情况经常发生,因为您自己的代码希望使用依赖项的一个版本,但您的一个外部依赖项指定了另一个冲突的版本。或者您有两个外部依赖关系,每个都需要不同的版本。)因为所有依赖项都是手动注入到特定模块中的,所以很容易理解它们。你知道一个事实:“在处理这个问题时,我需要考虑的唯一代码就是我有意选择在这里注入的代码”。因为甚至注入的模块的内容都封装在分配给它的变量后面,并且所有代码都在有限的范围内执行,所以意外和冲突变得非常不可能。在你没有意识到的情况下,你的一个依赖项中的某个东西会意外地重新定义一个全局变量,或者你会这样做。(这是可能发生的,但你通常必须用window.variable这样的方式去做。仍然会发生的一个意外是分配这个.variable,而没有意识到这实际上是当前上下文中的window。)当你想测试一个单独的模块时,你可以很容易地知道:到底还有什么(依赖关系)在影响模块内部运行的代码?而且,因为您显式地注入了所有内容,所以可以轻松地模拟这些依赖关系。
对我来说,前端代码模块的使用归结为:在更窄的环境中工作,更容易推理和测试,对发生的事情有更大的把握。
学习如何使用CommonJS/Node模块语法只需大约30秒。在将成为模块的给定JS文件中,首先声明要使用的任何外部依赖项,如下所示:
var React=要求(“响应”);
在文件/模块中,您可以做任何您通常会做的事情,并创建一些您希望向外部用户公开的对象或函数,称其为myModule。
在文件末尾,您可以导出任何您想与世界共享的内容,如下所示:
module.exports=myModule;
然后,要在浏览器中使用基于CommonJS的工作流,您将使用Browserify等工具抓取所有这些单独的模块文件,在运行时封装它们的内容,并根据需要将它们相互注入。
而且,由于ES6模块(您可能会使用Babel或类似工具将其转换为ES5)正在获得广泛接受,并且可以在浏览器或Node 4.0中使用,因此我们也应该对这些模块进行一个很好的概述。
有关使用本组模块的模式的更多信息。
编辑(2017年2月):Facebook的Yarn是当前npm的一个非常重要的潜在替代品/补充品:基于npm提供的快速、确定性、离线包管理。任何JS项目都值得一看,特别是因为它很容易进行交换。
编辑(2019年5月)“鲍尔终于被弃用了。故事结束了。”
而且,尽管Yarn仍然活跃,但一旦它采用了Yarn的一些关键功能,它的许多动力就转向了npm。
其他回答
我的团队从Bower搬到了npm,因为:
编程使用很痛苦Bower的界面不断变化有些功能,如url速记,完全被破坏了在同一项目中同时使用Bower和npm是很痛苦的保持bower.json版本字段与git标记同步非常困难源代码管理!=包裹管理CommonJS支持并不简单
有关详细信息,请参阅“为什么我的团队使用npm而不是bower”。
Bower维护单一版本的模块,它只会帮助您选择正确/最佳的模块。
Javascript依赖管理:npm vs bower vs volo?
NPM对于节点模块更好,因为有一个模块系统,您在本地工作。Bower对浏览器很好,因为目前只有全局范围,您需要对所使用的版本非常有选择。
TL;DR:日常使用中最大的区别不是嵌套依赖关系。。。这是模块和全局变量之间的区别。
我认为之前的海报很好地涵盖了一些基本的区别。(npm对嵌套依赖的使用确实非常有助于管理大型、复杂的应用程序,尽管我认为这不是最重要的区别。)
然而,我很惊讶,没有人明确解释鲍尔和npm之间最根本的区别之一。如果你阅读上面的答案,你会看到npm上下文中经常使用的单词“modules”。但这是随便提及的,好像它甚至可能只是语法上的差异。
但模块与全局(或模块与“脚本”)的区别可能是Bower和npm之间最重要的区别。将所有内容放入模块的npm方法要求您改变为浏览器编写Javascript的方式,几乎可以肯定是为了更好。
Bower方法:全球资源,如<script>标签
在根目录中,Bower负责加载普通的旧脚本文件。无论这些脚本文件包含什么,Bower都会加载它们。这基本上意味着Bower就像将所有脚本都包含在HTML的<head>中。
所以,这是您习惯的基本方法,但您可以获得一些很好的自动化便利:
您过去需要在项目库中包含JS依赖项(在开发时),或者通过CDN获取它们。现在,你可以跳过回购中的额外下载重量,有人可以快速安装bower,并立即在本地获得他们需要的内容。如果Bower依赖项随后在其Bower.json中指定了自己的依赖项,那么也会为您下载这些依赖项。
但除此之外,鲍尔并没有改变我们编写javascript的方式。Bower加载的文件中的内容根本不需要更改。特别是,这意味着Bower加载的脚本中提供的资源(通常,但不总是)仍然被定义为全局变量,可以从浏览器执行上下文中的任何位置获得。
npm方法:公共JS模块、显式依赖注入
Node land中的所有代码(以及通过npm加载的所有代码)都被构造为模块(具体来说,作为CommonJS模块格式的实现,或者现在作为ES6模块)。因此,如果您使用NPM来处理浏览器端的依赖关系(通过Browserify或其他执行相同任务的工具),那么您将以Node的方式构造代码。
比我更聪明的人解决了“为什么选择模块?”的问题,但这里有一个胶囊摘要:
模块中的任何内容都是有效的名称空间,这意味着它不再是一个全局变量,您不能无意中引用它。模块内的任何内容都必须有意地注入到特定上下文(通常是另一个模块)中,以便利用它这意味着您可以在应用程序的不同部分拥有相同外部依赖项(比如lodash)的多个版本,并且它们不会发生冲突。(这种情况经常发生,因为您自己的代码希望使用依赖项的一个版本,但您的一个外部依赖项指定了另一个冲突的版本。或者您有两个外部依赖关系,每个都需要不同的版本。)因为所有依赖项都是手动注入到特定模块中的,所以很容易理解它们。你知道一个事实:“在处理这个问题时,我需要考虑的唯一代码就是我有意选择在这里注入的代码”。因为甚至注入的模块的内容都封装在分配给它的变量后面,并且所有代码都在有限的范围内执行,所以意外和冲突变得非常不可能。在你没有意识到的情况下,你的一个依赖项中的某个东西会意外地重新定义一个全局变量,或者你会这样做。(这是可能发生的,但你通常必须用window.variable这样的方式去做。仍然会发生的一个意外是分配这个.variable,而没有意识到这实际上是当前上下文中的window。)当你想测试一个单独的模块时,你可以很容易地知道:到底还有什么(依赖关系)在影响模块内部运行的代码?而且,因为您显式地注入了所有内容,所以可以轻松地模拟这些依赖关系。
对我来说,前端代码模块的使用归结为:在更窄的环境中工作,更容易推理和测试,对发生的事情有更大的把握。
学习如何使用CommonJS/Node模块语法只需大约30秒。在将成为模块的给定JS文件中,首先声明要使用的任何外部依赖项,如下所示:
var React=要求(“响应”);
在文件/模块中,您可以做任何您通常会做的事情,并创建一些您希望向外部用户公开的对象或函数,称其为myModule。
在文件末尾,您可以导出任何您想与世界共享的内容,如下所示:
module.exports=myModule;
然后,要在浏览器中使用基于CommonJS的工作流,您将使用Browserify等工具抓取所有这些单独的模块文件,在运行时封装它们的内容,并根据需要将它们相互注入。
而且,由于ES6模块(您可能会使用Babel或类似工具将其转换为ES5)正在获得广泛接受,并且可以在浏览器或Node 4.0中使用,因此我们也应该对这些模块进行一个很好的概述。
有关使用本组模块的模式的更多信息。
编辑(2017年2月):Facebook的Yarn是当前npm的一个非常重要的潜在替代品/补充品:基于npm提供的快速、确定性、离线包管理。任何JS项目都值得一看,特别是因为它很容易进行交换。
编辑(2019年5月)“鲍尔终于被弃用了。故事结束了。”
而且,尽管Yarn仍然活跃,但一旦它采用了Yarn的一些关键功能,它的许多动力就转向了npm。
所有包管理器都有许多缺点。你只需要选择你能和谁一起生活。
历史
npm最初是管理node.js模块的(这就是为什么默认情况下包会进入node_modules),但当与Browserify或webpack结合时,它也适用于前端。
Bower专为前端而设计,并为此进行了优化。
回购规模
npm比bower大得多,包括通用JavaScript(如国家信息的国家数据或排序功能的排序,可在前端或后端使用)。
鲍尔的包裹数量要少得多。
样式处理等
Bower包括款式等。
npm专注于JavaScript。样式可以单独下载,也可以根据npm-sass或sas-npm等要求下载。
依赖关系处理
最大的区别是,npm执行嵌套依赖关系(但默认情况下是扁平的),而Bower需要一个扁平的依赖关系树(将依赖关系解析的负担推给用户)。
嵌套的依赖关系树意味着您的依赖关系可以有自己的依赖关系,这些依赖关系可以是自己的,依此类推。这允许两个模块需要相同依赖关系的不同版本,并且仍然可以工作。注意,自npm v3以来,依赖关系树默认为平面(节省空间),仅在需要时嵌套,例如,如果两个依赖关系需要自己的Undercore版本。
一些项目同时使用这两种工具:他们使用Bower作为前端包,使用npm作为开发工具,如Yeoman、Grunt、Gulp、JSHint、CoffeeScript等。
资源
嵌套依赖关系-深入了解node_modules的工作方式
对于许多使用node.js的人来说,bower的一个主要好处是管理根本不是javascript的依赖关系。如果他们使用的是编译为javascript的语言,那么可以使用npm来管理他们的一些依赖关系。然而,并不是所有的依赖都是node.js模块。一些编译为javascript的代码可能有奇怪的源语言特定的篡改,这使得在用户期望源代码时,将它们传递给编译为javascript是一个不合适的选项。
并非npm包中的所有内容都需要面向用户的javascript,但对于npm库包,至少其中一些应该是面向用户的。
推荐文章
- 如何使用Jest测试对象键和值是否相等?
- 将长模板文字行换行为多行,而无需在字符串中创建新行
- 如何在JavaScript中映射/减少/过滤一个集?
- Bower: ENOGIT Git未安装或不在PATH中
- 添加javascript选项选择
- 在Node.js中克隆对象
- 为什么在JavaScript的Date构造函数中month参数的范围从0到11 ?
- 使用JavaScript更改URL参数并指定默认值
- 在window.setTimeout()发生之前取消/终止
- 如何删除未定义和空值从一个对象使用lodash?
- 检测当用户滚动到底部的div与jQuery
- 在JavaScript中检查字符串包含另一个子字符串的最快方法?
- 检测视口方向,如果方向是纵向显示警告消息通知用户的指示
- ASP。NET MVC 3 Razor:在head标签中包含JavaScript文件
- 禁用从HTML页面中拖动图像