Bower和npm有何区别?

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


npm最常用于管理Node.js模块,但它与Browserify和/或$ npm dedupe结合使用时也可用于前端。

Bower专为前端而开发,并且在考虑到这一点的情况下进行了优化。 最大的区别是npm确实嵌套了依赖树(大小很大),而Bower需要一个平坦的依赖关系树(将依赖关系解析的负担放在用户上)。

嵌套的依赖关系树意味着您的依赖关系可以拥有自己的依赖关系,这些依赖关系可以拥有自己的依赖关系,依此类推。 这在服务器上非常棒,您不必太在意空间和延迟。 它使您不必关心依赖冲突,因为所有的依赖关系都使用它们自己的Underscore版本。 这在前端显然不太适用。 想象一个网站必须下载jQuery的三份副本。

许多项目都使用它们的原因是,他们使用Bower作为前端程序包,使用npm作为开发人员工具,如Yeoman,Grunt,Gulp,JSHint,CoffeeScript等。

所有软件包管理者都有很多缺点。 你只需要选择你可以住的地方。


资源

  • 嵌套依赖关系 - 深入了解为什么node_modules的工作方式如此

  • 这个答案是对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)。

  • [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的文档


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

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

    然而,我很惊讶,没有人明确地解释过鲍尔和npm之间最根本的区别之一。 如果你阅读上面的答案,你会看到经常在npm环境中使用的单词'modules'。 但它随便提到,好像它甚至可能只是一个语法差异。

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

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

    在根目录下,Bower是关于加载纯文本脚本文件的。 无论那些脚本文件包含什么,Bower都会加载它们。 这基本上意味着Bower就像将所有脚本包含在HTML的<head>中的普通旧<script>中。

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

  • 你以前需要在你的项目库(包括开发)中包含JS依赖项,或者通过CDN获取它们。 现在,您可以跳过回购中的额外下载权重,并且有人可以快速bower install并立即在本地bower install它们所需的内容。
  • 如果一个Bower依赖项在它的bower.json指定了它自己的依赖项,那么这些依赖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模块(您可能会用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?