Bower 和 npm 有什么区别?

IT技术 javascript npm bower
2021-02-09 13:16:44

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

6个回答

所有的包管理器都有很多缺点。你只需要选择你可以忍受的。

历史

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

Bower专为前端创建,并考虑到这一点进行了优化。

回购规模

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

Bower 的包数量要少得多。

样式处理等

Bower 包括样式等。

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

依赖处理

最大的不同是 npm 做嵌套依赖(但默认是扁平的),而 Bower 需要扁平的依赖树(把依赖解析的负担放在用户身上)

嵌套依赖树意味着您的依赖项可以拥有自己的依赖项,这些依赖项可以拥有自己的依赖项,依此类推。这允许两个module需要相同依赖项的不同版本并且仍然可以工作。请注意,从 npm v3 开始,依赖树默认是扁平的(节省空间)并且只在需要的地方嵌套,例如,如果两个依赖项需要它们自己的 Underscore 版本。

一些项目同时使用两者:他们使用 Bower 作为前端包,使用 npm 作为开发工具,如 Yeoman、Grunt、Gulp、JSHint、CoffeeScript 等。


资源

“扁平依赖树”是什么意思?扁平树是什么——一个列表?那么它不是一棵树。
2021-03-19 13:16:44
其实,路径也是一棵树。这只是一个特例。来自维基百科:“在数学中,更具体地说,在图论中,树是一种无向图,其中任何两个顶点都由一条路径连接。”
2021-03-23 13:16:44
为什么嵌套的依赖树在前端做得不好?
2021-03-25 13:16:44
npm 3 现在支持平面依赖树。
2021-03-25 13:16:44
前端 npm 包是否也不是平面依赖树?我面临着“为什么我们需要 2 个包管理器?” 困境。
2021-04-04 13:16:44

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

关于npm 常见问题(archive.org 链接,2015 年 9 月 6 日)

不嵌套依赖就很难避免依赖冲突。这是 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 需要一个与依赖项 C 不同版本的依赖项 A。 npm 安装了这个依赖项的两个版本,所以它无论如何都可以工作,但是 Bower 会给你一个冲突,因为它不喜欢重复(因为在网页上加载相同的资源是非常低效且成本高昂,还会产生一些严重的错误)。您必须手动选择要安装的版本。这可能会导致依赖项之一中断,但无论如何您都需要修复它。

因此,常见的用法是 Bower 用于您要在网页上发布的包(例如运行时,避免重复),并将 npm 用于其他内容,例如测试、构建、优化、检查等(例如开发时间),其中重复问题较少)。

npm 3 的更新:

与 Bower 相比,npm 3 的处理方式仍然不同。它将全局安装依赖项,但仅针对它遇到的第一个版本。其他版本安装在树中(父module,然后是 node_modules)。

  • [节点module]
    • 深度 A v1.0
    • 深度 B v1.0
      • 深度 A v1.0 (使用根版本)
    • DEP C v1.0
      • dep A v2.0(此版本与root版本不同,所以会嵌套安装)

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

@AlexAngas 我为 npm3 添加了更新。与 Bower 相比,它仍然存在一些重大差异。npm 可能总是支持多个版本的依赖项,而 Bower 不支持。
2021-03-15 13:16:44
@Shrek 我暗示您实际上可以同时使用两者。正如我在最后一段所述,它们有不同的目的。在我看来,这不是一种权衡。
2021-03-18 13:16:44
啊,我知道我误会你了。或者我读得不够仔细。感谢您的澄清。:-) 两者都可以使用而无需权衡,这很好。
2021-03-28 13:16:44
现在,“软件开发就是权衡取舍”几乎是陈词滥调。这是一个很好的例子。必须选择要么具有更大的稳定性npm 最小的资源负载bower
2021-03-30 13:16:44
npm 3 越来越接近凉亭;)
2021-04-02 13:16:44

TL;DR:日常使用中最大的区别不是嵌套依赖……而是module和全局变量之间的区别。

我认为之前的海报已经很好地涵盖了一些基本区别。(npm 使用嵌套依赖确实对管理大型复杂应用程序非常有帮助,尽管我认为这不是最重要的区别。)

然而,令我惊讶的是,没有人明确解释 Bower 和 npm 之间最基本的区别之一。如果您阅读上述答案,您会看到 npm 上下文中经常使用的“module”一词。但它被随意提及,好像它甚至可能只是一个语法差异。

但是这种module与全局变量(或module与“脚本”)的区别可能是 Bower 和 npm 之间最重要的区别。将所有内容放入module的 npm 方法要求您更改为浏览器编写 Javascript 的方式,几乎肯定会变得更好。

Bower 方法:全球资源,如<script>标签

从根本上说,Bower 是关于加载普通的脚本文件。无论这些脚本文件包含什么,Bower 都会加载它们。这基本上意味着 Bower 就像将所有脚本包含在HTML中的普通<script>'s 中一样<head>

因此,与您习惯的基本方法相同,但您会获得一些不错的自动化便利:

  • 你曾经需要在你的项目 repo 中包含 JS 依赖项(在开发时),或者通过 CDN 获取它们。现在,您可以在 repo 中跳过额外的下载重量,并且有人可以bower install在本地快速并立即获得他们需要的东西。
  • 如果 Bower 依赖项在其 中指定了自己的依赖项,那么这些依赖bower.json项也会为您下载。

但除此之外,Bower 并没有改变我们编写 javascript 的方式Bower 加载的文件中的内容根本不需要更改。特别是,这意味着 Bower 加载的脚本中提供的资源(通常,但不总是)仍将定义为全局变量,可从浏览器执行上下文的任何位置使用。

npm 方法:通用 JS module,显式依赖注入

Node 中的所有代码(以及所有通过 npm 加载的代码)都被构建为module(具体来说,作为CommonJS module格式的实现,或者现在作为 ES6 module)。因此,如果您使用 NPM 来处理浏览器端的依赖项(通过 Browserify 或其他可以完成相同工作的东西),您将按照 Node 的方式构建代码。

比我更聪明的人已经解决了“为什么是module?”的问题,但这里有一个简单的总结:

  • module内的任何内容都是有效的命名空间,这意味着它不再是全局变量,并且您不能无意中意外引用它。
  • module内的任何内容都必须有意注入到特定上下文(通常是另一个module)中才能使用它
  • 这意味着您可以在应用程序的各个部分拥有相同外部依赖项(比如说 lodash)的多个版本,并且它们不会发生冲突/冲突。(这出乎意料地经常发生,因为您自己的代码想要使用一个版本的依赖项,但是您的一个外部依赖项指定了另一个冲突。或者您有两个外部依赖项,每个都需要不同的版本。)
  • 因为所有依赖项都是手动注入到特定module中的,所以很容易推断它们。您知道一个事实:“我在处理此问题时需要考虑的唯一代码是我有意选择在此处注入的代码”
  • 因为即使是注入module的内容也被封装在您分配给它的变量后面,并且所有代码都在有限的范围内执行,所以意外和冲突变得非常不可能。来自您的依赖项之一的某些内容在您没有意识到的情况下意外地重新定义全局变量的可能性要小得多,或者您会这样做。(它可能发生,但你通常必须用你的方式去做,比如window.variable。仍然容易发生的一个事故是赋值this.variable,没有意识到这this实际上是window在当前上下文中。)
  • 当您想测试单个module时,您可以很容易地知道:究竟还有什么(依赖项)影响了在module内运行的代码?而且,因为您明确地注入了所有内容,所以您可以轻松地模拟这些依赖项。

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


学习如何使用 CommonJS/Node module语法只需要大约 30 秒。在一个给定的 JS 文件中,它将成为一个module,你首先声明你想要使用的任何外部依赖项,如下所示:

var React = require('react');

在文件/module内部,您可以做任何您通常会做的事情,并创建一些您希望向外部用户公开的对象或函数,可能将其称为myModule.

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

module.exports = myModule;

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

而且,由于 ES6 module(您可能会使用 Babel 或类似工具将其转换为 ES5)正在获得广泛接受,并且可以在浏览器或 Node 4.0 中运行,因此我们也应该对这些module进行很好的概述

更多关于使用本套牌中的module的模式


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


编辑(2019 年 5 月)“鲍尔终于被弃用了。故事结束。” (h/t:@DanDascalescu,下面是简洁的总结。)

而且,虽然 Yarn仍然活跃,但一旦它采用了 Yarn 的一些关键特性,它的很多动力就会转移回 npm。

对不起,来自一个对 javascript parlands 中的所有模糊测试很少关心的人,但碰巧它经营一家使用小型 Web 应用程序的业务。最近被迫尝试 npm,从使用 bower 和我们用来开发该死的 web 东西的工具包开始。我可以告诉你,最大的区别是等待时间,npm 需要很长时间。请记住,这是编译 xkcd 卡通片,而那些玩剑术的家伙对他们的老板大喊“编译”;这几乎就是 npm 添加到 bower 的内容。
2021-03-16 13:16:44
很高兴这个答案在这里,其他流行的答案没有提到这个细节。npm 强制您编写module化代码。
2021-04-08 13:16:44

2017 年 10 月更新

Bower 终于被弃用了故事结局。

较旧的答案

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

在几乎所有情况下,使用 Browserify 和 npm 比 Bower 更合适。它只是比 Bower 更好的前端应用程序打包解决方案。在 Spotify,我们使用 npm 来打包整个 Web module(html、css、js),并且效果很好。

Bower 将自己打造成网络包管理器。如果这是真的,那就太棒了 - 一个让我的前端开发人员生活更美好的包管理器会很棒。问题是 Bower 没有为此提供专门的工具。它没有提供我知道 npm 没有的任何工具,尤其是没有提供对前端开发人员特别有用的工具。对于前端开发人员来说,使用 Bower 而不是 npm 没有任何好处。

我们应该停止使用 bower 并围绕 npm 进行整合。值得庆幸的是,这就是正在发生的事情

module计数 - bower 与 npm

使用 browserify 或 webpack,将所有module连接成大的缩小文件变得非常容易,这对性能来说非常棒,尤其是对于移动设备。Bower 并非如此,这将需要更多的劳动力才能获得相同的效果。

npm 还使您能够同时使用多个版本的module。如果你没有做过很多应用程序开发,这最初可能会让你觉得这是一件坏事,但是一旦你经历了几次依赖地狱,你就会意识到拥有一个module的多个版本的能力是一件非常糟糕的事情很棒的功能。需要注意的是NPM包括一个非常方便的重复数据删除工具,可自动确保您只使用一个module的两个版本,如果你确实到-如果两个module都可以使用一个module的版本相同,他们会的。但如果他们不能,你有一个非常方便的。

(请注意,截至2016 年 8 月,人们普遍认为Webpackrollup比 Browserify 更好。)

我不同意“大的缩小文件”“对性能来说很棒,尤其是对于移动设备”。恰恰相反:受限带宽需要小文件,按需加载。
2021-03-18 13:16:44
<sarcasm> 请记住,即使是“hello world” npm 项目也需要 300 多个module才能运行...</sarcasm> :O
2021-04-06 13:16:44
不是很好的建议。大多数 npm 包只是 nodejs 后端。如果你没有在后端做 javascript,或者你没有适当的module系统,那么包的数量是无关紧要的,因为 Bower 会更好地满足你的需求
2021-04-10 13:16:44
@GerardoGrignoli:凉亭即将推出
2021-04-10 13:16:44

Bower 维护单一版本的module,它只会尝试帮助您为您选择正确/最佳的module。

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

NPM 更适合节点module,因为有一个module系统并且您在本地工作。Bower 对浏览器很有用,因为目前只有全局范围,并且您希望对使用的版本非常有选择性。

@GamesBrainiac 你是对的,只是想我会用我自己的话来表达。
2021-03-15 13:16:44
@Sagivf 这些不是你自己的话,除非你也是在这里提供原始答案的 wheresrhys
2021-03-24 13:16:44
我觉得 Sindre 在谈到嵌套依赖时提到了这一点。
2021-03-28 13:16:44
我不知道你们为什么这么喜欢这个答案。在这个对我的回答中确实有新的信息/观点。
2021-03-29 13:16:44
@Sagivf如果他们自己没有在此处提供答案,则复制其他人答案的** 相关部分并没有错你说“我只是想我会用我自己的话来表达”,这让我有点烦躁。信用应该去信用到期的地方。
2021-03-31 13:16:44