将Require.js与Angular.js一起使用是否有意义?[关闭]


443

我是Angular.js的新手,试图了解它与Backbone.js的区别...我们以前在使用Backbone时使用Require.js管理我们的软件包依赖项。用Angular.js做同样的事情有意义吗?


另一个博客和种子项目:startersquad.com/blog/angularjs-requirejs
iwein

19
否-请勿将require.js或浏览器与Angular.JS一起使用-根本不需要这样做-AngularJS有一个模块系统,使用上面的另一个模块系统会使您的生活变得不必要。我遵循了该线程中的答案,并在完全不必要的事情上浪费了太多时间。请阅读这篇文章,解释为什么不:medium.com/@dickeyxxx/...
VitalyB


1
这是一段很棒的视频,解释了为什么这是一个好主意,并展示了如何将requireJS与angularJS一起使用youtube.com/watch?v=4yulGISBF8w#t=142
gskalinskii 2014年

2
@VitalyB好文章!我更喜欢以小块形式加载应用程序。它不会很快就花钱。哎呀,现在对我来说什么都不花钱。
dsign

Answers:


224

是的,angular.jsrequire.jsrequire.js组件模块化一起使用时,这是有意义的。

有一个使用的种子项目both angular.js and require.js


108
上面提到的种子项目已经有一年了,所以我使用最新的AngularJS和RequireJS创建了一个新项目,并全面支持了眼驱动测试。
tnajdek

2
@tnajdek,我更新了Anshu答案中的链接,以指向您建议的链接。
David Rivers

7
请注意,这些种子项目均未获得Angular团队的认可。需求是一种在其他情况下更有意义的模式,恕我直言,将它塞入Angular并不是最佳实践。
XML

2
Brad Green&Shyam Seshadri撰写的O'Reilly AngularJS书(今年4月发行)还建议在Angular项目的早期阶段添加RequireJS,并清晰地列出细节。
bjorke

1
我宁愿在编译的时候做的一切1. browserify.org 2. npmjs.org/package/gulp-angular-filesort
A-Dubb

150

重申一下,我认为OP的问题实际上是:

如果我主要是在Angular 1.x中构建应用程序,并且(隐式地)在Grunt / Gulp / Broccoli和Bower / NPM时代这样做,并且我可能还有其他一些库依赖项,是否需要添加明确,具体的信息是否超出了使用Angular而无需Require所获得的价值?

或者,换一种说法:

如果我还有其他处理基本脚本加载的方法,香草Angular是否需要有效管理基本Angular组件加载?

我相信对此的基本答案是:“除非您正在做其他事情,并且/或者您无法使用更新,更现代的工具,否则不可以。”

首先,我们要弄清楚:RequireJS是一个出色的工具,它解决了一些非常重要的问题,使我们踏上了通往更可扩展,更专业的Javascript应用程序的道路。重要的是,这是许多人第一次遇到模块化的概念,并使事情脱离全球范围。因此,如果您要构建需要扩展的Javascript应用程序,那么Require和AMD模式并不是执行此操作的好工具。

但是,关于Angular有什么特别之处使Require / AMD非常合适?不会。事实上,Angular为您提供了自己的模块化和封装模式,这在许多方面都使AMD的基本模块化功能变得多余。而且,将Angular模块集成到AMD模式并不是没有可能,但这有点...有点挑剔。您肯定会花时间使这两种模式很好地集成。

从Angular团队本身的角度来看,是Angular Batarang的作者,现在Angular核心团队的成员Brian Ford的:

我不建议将RequireJS与AngularJS一起使用。尽管确实有可能,但我还没有看到RequireJS在实践中有益的任何实例。

因此,在AngularJS的一个非常具体的问题上:Angular和Require / AMD是正交的,并且在某些地方重叠。您可以将它们一起使用,但是没有理由与Angular本身的性质/图案特别相关。

但是,可伸缩Javascript应用程序的内部和外部依赖关系的基本管理又如何呢?不需要在我那里做对我来说很重要的事情吗?

我建议检查Bower和NPM,尤其是NPM。我并不是要就这些工具的相对优势发动一场圣战。我只想说:还有其他方法可以使猫咪皮肤,并且这些方法甚至可能比AMD / Required更好。(在2015年末,它们无疑具有更受欢迎的势头,尤其是与ES6或CommonJS模块结合的NPM。请参见相关的SO问题。)

延迟加载呢?

请注意,延迟加载和延迟下载是不同的。Angular的延迟加载并不意味着您直接将它们从服务器中拉出。在具有javascript自动化功能的Yeoman风格应用程序中,您将整个shebang串联在一起并缩小到一个文件中。它们存在,但是直到需要时才执行/实例化。通过这样做,您获得的速度和带宽改进大大超过了延迟下载特定20行控制器的任何所谓的改进。实际上,该控制器所浪费的网络等待时间和传输开销将比控制器本身的大小大一个数量级。

但是,假设您确实确实需要延迟下载,也许是对于不经常使用的应用程序部分(例如管理界面)。那是一个非常合理的情况。确实可以为您做到这一点。但是,还有 许多 其他的可能 灵活的 选项可以完成相同的任务。Angular 2.0显然会为我们解决这个问题,它是路由器内置的。(详细信息。)

但是在我本地开发者Boxen的开发过程中呢?

我如何才能加载所有数十个/数百个脚本文件,而无需将它们全部手动附加到index.html?

看一下Yeoman的generator-angular中的子生成器,或generator- gulp -angular中体现的自动化模式,或React的标准Webpack自动化。这些为您提供了一种干净,可扩展的方法,可以:在搭建脚手架时自动附加文件,或者在某些文件夹中存在某些文件/匹配某些glob模式时简单地自动抓取它们。一旦有了后一种选择,您就不再需要考虑自己的脚本加载。

底线?

对于某些事情,Require是一个很棒的工具。但是,只要有可能就顺其自然,并尽可能将您的关注点分开。让Angular担心Angular自己的模块化模式,并考虑使用ES6模块或CommonJS作为通用模块化模式。让现代自动化工具担心脚本加载和依赖关系管理。并且以细粒度的方式照顾异步延迟加载,而不是将其与其他两个问题缠在一起。

就是说,如果您正在开发Angular应用程序,但由于某种原因而无法在计算机上安装Node以使用Javascript自动化工具,那么Require可能是一个不错的替代解决方案。我已经看到了非常复杂的设置,人们想要动态加载每个Angular组件,每个组件声明自己的依赖关系或其他内容。尽管我可能会尝试以另一种方式解决该问题,但对于那种非常特殊的情况,我可以看到这个想法的优点。

但是否则,当从头开始使用新的Angular应用程序以及创建现代自动化环境的灵活性时,您还有许多其他更灵活,更现代的选择。

(反复更新以适应不断发展的JS场景。)


1
NG-Boilerplate种子项目(github.com/ngbp/ngbp)还创建了一个带有一个js文件的单页webapp。使用HTML5清单可确保该文件每个版本仅加载一次。
Federico Elles 2014年

2
不过,<i>取决于情况</ i>。许多人将Require用于其整个体系结构,并且需要将Angular集成到该生态系统中。与隔离构建应用程序时的情况大不相同。
戴夫·尼科尔

2
同意 但是OP的工作重点似乎是:“如果我主要是在Angular中构建应用程序,并且(隐式)在Grunt时代这样做,并且我可能还有几个其他的库依赖项,那么Require是否需要添加明确的,特定的值我不用Angular就能得到什么?” 我相信答案是:不会。如果您的大型应用程序具有40个外部依赖项,或者您无法控制自己的CI环境,或者您的老板崇拜Require,或者您崇拜Require,或者Angular只是大型应用程序的一部分,依此类推,等等。 YMMV。
XML

1
但是由于他似乎没有问这些问题,并且因为他只是提到了Backbone应用程序的替代上下文,所以他似乎在问:“香草Angular是否需要有效管理其组件?” 答案是:“除非您有其他事情要做,否则不会。” 同样,这个问题来自Javascript CI运动的风口浪尖,在Java运动中,我们有了更好的方法来处理基本的物理“脚本加载”。如果您解决了该问题,那么Require基本上是有关依赖项匹配和封装的。Angular为您完成了这两项工作。
XML

Google在其某些AngularJS项目中使用了延迟加载,因为否则,用户将在第一页加载时下载24mb的文件(这是经过合并和合并的文件)。因此,是的,在复杂的应用程序中,并不能仅连接所有部分,当有部分用户不会每次访问时都打开。
ngDeveloper 2015年

136

是的,这很有道理。

Angular模块不会尝试解决脚本加载顺序或延迟脚本获取的问题。这些目标是正交的,并且两个模块系统都可以并存并实现其目标。

资料来源:Angular JS官方网站


6
如果每个js文件使用一个模块,则可以按任何顺序加载angular模块。但是,如果要将不同的服务放在不同的js文件中,但又想将它们附加到同一angular模块上,则必须在服务声明之前加载模块声明。因此,这是一项体系结构决策。
Matohawk

@Tiago:请提供指向您来源来源的链接。我在任何地方都找不到。我猜想它来自Angular文档的早期版本,在Angular的模式已经被很好地建立之前,并且在清楚地表明避免使用Require(至少对于Angular组件)有明显的优势之前。
XML

@XMLilley:您能否提供一个链接来说明使用Angular时避免使用Require的优点?我正在决定是否在我的项目中使用Require,这听起来会很有帮助。
Trevor

1
我在这里用我的语言不清楚:充分利用Angular自己的内置模块加载器并遵循Angular模式的优点。问题不是是否要避免使用 Require,而是增加附加的复杂性层是否有价值。显而易见的是,Angular的内置模式将轻松而优雅地满足加载Angular自身模块的需求。如果Require是出于在Angular上下文之外加载模块的目的,那么就这样吧。但是使用Require for Angular是多余的。
XML

6
@XMLilley Angular所做的只是给您依赖注入。模块的实际加载是您的责任。您可以通过添加脚本标签,使用构建脚本或使用requirejs来实现。Angulars模块系统对此没有意见。
gillesruppert

57

我认为这是一个主观问题,因此我将提供我的主观意见。

Angular具有内置的模块化机制。创建应用程序时,要做的第一件事是

var app = angular.module("myApp");

然后

app.directive(...);

app.controller(...);

app.service(...);

如果您看一下角度种子,它是用于角度的整洁的入门应用程序,则他们将指令,服务,控制器等分离到不同的模块中,然后将这些模块作为依赖项加载到您的主应用程序中。

就像是 :

var app = angular.module("myApp",["Directives","Controllers","Services"];

Angular也会延迟将这些模块(而不是脚本文件)加载到内存中。

对于延迟加载脚本文件而言,坦率地说,除非您要编写非常大的内容,否则这将是多余的,因为从本质上讲,角度化会减少您编写的代码量。如果使用角度编写,则在大多数其他框架中编写的典型应用程序的LOC可能会降低约30-50%。


5
实际上,在Angular.js中配置服务要比使用Require.js加载模块更好。这使得它更容易与$范围和服务方面发挥,因为我Socket.io玩
马可Godínez

33

将RequireJS与AngularJS结合使用是有意义的,但前提是您了解它们各自在依赖注入方面的工作方式,就像它们都注入依赖项一样,它们注入的东西也非常不同。

AngularJS拥有自己的依赖系统,可让您将AngularJS模块注入到新创建的模块中以重用实现。假设您创建了一个实现AngularJS过滤器“ greet”的“第一个”模块:

angular
  .module('first', [])
  .filter('greet', function() {
    return function(name) {
      return 'Hello, ' + name + '!';
    }
  });

现在,假设您要在另一个名为“ second”的模块中使用“ greet”过滤器,该模块实现了“再见”过滤器。您可以这样做,将“第一个”模块注入“第二个”模块:

angular
  .module('second', ['first'])
  .filter('goodbye', function() {
    return function(name) {
      return 'Good bye, ' + name + '!';
    }
  });

事实是,为了在没有RequireJS的情况下正常工作,您必须确保在创建“第二” AngularJS模块之前在页面上加载了“第一个” AngularJS模块。报价文件:

取决于模块意味着需要在加载需求模块之前先加载需求模块。

从这种意义上说,RequireJS可以在这里为您提供帮助,因为RequireJS提供了一种将脚本注入页面的干净方法,以帮助您组织彼此之间的脚本依赖关系。

回到“第一个”和“第二个” AngularJS模块,这是使用RequireJS将不同文件上的模块分开以利用脚本依赖项加载的方法:

// firstModule.js file
define(['angular'], function(angular) {
  angular
    .module('first', [])
    .filter('greet', function() {
      return function(name) {
        return 'Hello, ' + name + '!';
      }
    });
});
// secondModule.js file
define(['angular', 'firstModule'], function(angular) {
  angular
    .module('second', ['first'])
    .filter('goodbye', function() {
      return function(name) {
        return 'Good bye, ' + name + '!';
      }
    });
});

可以看到,在执行RequireJS回调的内容之前,我们依赖于要插入的“ firstModule”文件,该文件需要加载“第一个” AngularJS模块以创建“第二个” AngularJS模块。

旁注:为了在RequireJS回调函数中使用AngularJS,需要在“ firstModule”和“ secondModule”文件上注入“ Angular”作为依赖项,并且必须在RequireJS config上对其进行配置以将“ angular”映射到库代码。您可能也会以传统方式(脚本标记)将AngularJS加载到页面上(尽管失败了RequireJS的好处)。

在我的博客文章中,有关从2.0版本的AngularJS core获得RequireJS支持的更多详细信息。

根据我的博客文章“使用AngularJS感知RequireJS”,此处是链接


2
实际上,当包括链接时,最好在Stack Overflow上总结链接的内容。如果您要断开的链接(Internet上的链接已经断开),那么您的答案对将来的访问者将毫无用处。考虑进行编辑以总结并改进本文。祝好运!
jmort253

3
到了,谢谢jmort253。
leog

感谢您进行这些编辑并解释了RequireJS如何帮助管理依赖项,以避免Angular尝试加载尚不存在的问题。
jmort253 2014年

我完全同意,最好将这种方法用于大型应用程序,否则您的应用程序中将有多个<script>标签。
I.Tyger '16

21

正如@ganaraj提到的那样,AngularJS的核心是依赖注入。在使用和不使用RequireJS的情况下构建玩具种子应用程序时,我个人发现RequireJS对于大多数用例而言可能是过大的。

这并不意味着RequireJS对它的脚本加载功能以及在开发过程中保持代码库干净无用。将r.js优化器(https://github.com/jrburke/r.js)与杏仁(https://github.com/jrburke/almond)结合可以创建一个非常苗条的脚本加载故事。但是,由于它的依赖性管理功能对于应用程序核心中的angular并不那么重要,因此您还可以评估其他客户端(HeadJS,LABjs等),甚至服务器端(MVC4 Bundler等)脚本加载解决方案针对您的特定应用。


17

是的,它确实适用于大型SPA。

在某些情况下,RequireJS是必须的。例如,我使用AngularJS开发PhoneGap应用程序,该应用程序也使用Google Map API。如果没有像RequireJS这样的AMD加载程序,该应用程序将在离线时启动时崩溃,因为它无法获取Google Map API脚本。AMD加载程序使我有机会向用户显示错误消息。

但是,AngularJS和RequireJS之间的集成有些棘手。我创建了angularAMD来简化此过程:

http://marcoslin.github.io/angularAMD/




7

是的,将requireJS与Angular一起使用是有意义的,我花了几天时间测试了几种技术解决方案。

我在服务器端使用RequireJS制作了一个Angular Seed。很简单的一个。我将SHIM表示法用于没有AMD模块而不是AMD的原因,因为我认为处理两种不同的依赖注入系统非常困难。

我使用grunt和r.js在服务器上串联js文件,这取决于SHIM配置(依赖项)文件。所以我只在我的应用程序中引用一个js文件。

有关更多信息,请访问我的github Angular Seed:https : //github.com/matohawk/angular-seed-requirejs


3

我会避免使用Require.js。我所见过的应用程序可以完成多种类型的模块模式架构。AMD,Revealing,IIFE的不同口味等。还有其他按需加载的方法,例如loadOnDemand Angular mod。添加其他内容只会使您的代码充满混乱,并产生低信噪比,并使您的代码难以阅读。




0

我认为这取决于您的项目复杂性,因为angular几乎是模块化的。您的控制器可以被映射,您只需将这些JavaScript类导入index.html页面即可。

但是如果您的项目越来越大。或者您预期这种情况,则应将angular与requirejs集成。在文章中,你可以看到这样的集成演示应用程序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.