Bower和npm有何区别?
bower
和npm
之间的根本区别是什么? 只是想要简单明了的东西。 我看到一些同事在他们的项目中交替使用了bower
和npm
。
npm最常用于管理Node.js模块,但它与Browserify和/或$ npm dedupe
结合使用时也可用于前端。
Bower专为前端而开发,并且在考虑到这一点的情况下进行了优化。 最大的区别是npm确实嵌套了依赖树(大小很大),而Bower需要一个平坦的依赖关系树(将依赖关系解析的负担放在用户上)。
嵌套的依赖关系树意味着您的依赖关系可以拥有自己的依赖关系,这些依赖关系可以拥有自己的依赖关系,依此类推。 这在服务器上非常棒,您不必太在意空间和延迟。 它使您不必关心依赖冲突,因为所有的依赖关系都使用它们自己的Underscore版本。 这在前端显然不太适用。 想象一个网站必须下载jQuery的三份副本。
许多项目都使用它们的原因是,他们使用Bower作为前端程序包,使用npm作为开发人员工具,如Yeoman,Grunt,Gulp,JSHint,CoffeeScript等。
所有软件包管理者都有很多缺点。 你只需要选择你可以住的地方。
资源
这个答案是对Sindre Sorhus答案的补充。 npm和Bower之间的主要区别在于它们处理递归依赖的方式。 请注意,它们可以在一个项目中一起使用。
在npm FAQ上:
如果没有嵌套依赖关系,避免依赖冲突要困难得多。 这是npm工作方式的基础,并且已被证明是非常成功的方法。
在Bower主页上:
Bower针对前端进行了优化。 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,并将npm用于测试,构建,优化,检查等其他内容(例如开发时间,重复不太重要)。
npm 3更新:
与Bower相比,npm 3仍然有所不同。 它将全局安装依赖关系,但仅限于遇到的第一个版本。 其他版本安装在树中(父模块,然后是node_modules)。
欲了解更多信息,我建议阅读npm 3的文档
TL; DR:日常使用中最大的区别不是嵌套依赖......这是模块和全局变量之间的区别。
我认为以前的海报已经涵盖了一些基本的区别。 (npm使用嵌套依赖对管理大型复杂应用程序确实非常有帮助,但我认为这不是最重要的区别。)
然而,我很惊讶,没有人明确地解释过鲍尔和npm之间最根本的区别之一。 如果你阅读上面的答案,你会看到经常在npm环境中使用的单词'modules'。 但它随便提到,好像它甚至可能只是一个语法差异。
但是, 模块与全局模块 (或模块与“脚本”)的区别可能是Bower和npm之间最重要的区别。 将所有内容放在模块中的npm方法要求您改变为浏览器编写Javascript的方式,几乎肯定会更好。
Bower方法:全球资源,就像<script>
标签
在根目录下,Bower是关于加载纯文本脚本文件的。 无论那些脚本文件包含什么,Bower都会加载它们。 这基本上意味着Bower就像将所有脚本包含在HTML的<head>
中的普通旧<script>
中。
因此,您习惯的基本方法是相同的,但您会获得一些不错的自动化便利:
bower install
并立即在本地bower install
它们所需的内容。 bower.json
指定了它自己的依赖项,那么这些依赖bower.json
也会被下载。 但除此之外,Bower不会改变我们如何编写javascript。 关于Bower加载的文件里面的内容什么都不需要改变。 特别是,这意味着由Bower加载的脚本中提供的资源将(通常但不总是)仍然被定义为全局变量,可以在浏览器执行上下文中的任何地方使用。
npm方法:通用JS模块,显式依赖注入
Node中的所有代码(并且因此所有通过npm加载的代码)都被构造为模块(具体地,作为CommonJS模块格式的实现,或者现在作为ES6模块)。 因此,如果您使用NPM来处理浏览器端的依赖关系(通过Browserify或其他执行相同工作的东西),您将按照Node的相同方式构建代码。
比我更聪明的人解决了“为什么模块?”的问题,但这里有一个胶囊摘要:
window.variable
一样。仍然倾向于发生的一个事故是分配这个this.variable
,并没有意识到this
实际上是当前的window
上下文。) 对我而言,前端代码模块的使用归结为:工作在更狭窄的环境中,更容易推理和测试,并对发生的事情有更大的把握。
学习如何使用CommonJS / Node模块语法只需要大约30秒。 在一个给定的JS文件中,它将成为一个模块,你首先声明你想要使用的任何外部依赖关系,如下所示:
var React = require('react');
在文件/模块内部,你可以做任何你通常会做的事情,并创建一些你想要暴露给外部用户的对象或函数,称之为myModule
。
在文件结尾处,您可以导出任何想要与世界分享的内容,如下所示:
module.exports = myModule;
然后,为了在浏览器中使用基于CommonJS的工作流程,您将使用像Browserify这样的工具来抓取所有这些单独的模块文件,在运行时封装它们的内容,并根据需要将它们注入彼此。
而且,由于ES6模块(您可能会用Babel或类似的方式将其转换为ES5)正在得到广泛接受,并且可以在浏览器或Node4.0中使用,我们也应该提及这些模块。
更多关于在这套牌中使用模块的模式。
编辑(2017年2月):Facebook的纱线现在是npm非常重要的潜在替代/补充:快速,确定性,离线包管理,建立在npm为您提供的基础上。 值得一看的任何JS项目,特别是因为它很容易交换它进/出。
链接地址: http://www.djcxy.com/p/2977.html上一篇: What is the difference between Bower and npm?
下一篇: What is the difference between String.slice and String.substring?