使用Require.js和Angular.js是否有意义?

我是Angular.js的新手,并试图理解它与Backbone.js是如何不同的…我们曾经在使用Backbone时使用Require.js来pipe理包依赖。 用Angular.js做同样的事情有意义吗?

是的,使用angular.jsrequire.js是有道理的,其中您可以使用require.js来模块化组件。

我可以指给你一个使用both angular.js and require.js的种子项目 。 希望有所帮助!

重申我认为OP的问题真的是:

如果我主要在Angular 1.x中构build一个应用程序,并且(隐式地)在Grunt / Gulp / Broccoli和Bower / NPM时代这样做,并且我可能还有一些额外的库依赖项,那么是否需要添加明确的,特定的超越我通过使用Angular而无需获得的价值?

或者换一种说法:

如果我有其他方法来处理基本的脚本加载那么 vanilla Angular需要有效地pipe理基本的Angular组件加载吗?

我相信这个基本的答案是:“除非你还有别的事情要做,否则你不能使用更新,更现代的工具。”

让我们从一开始就清楚:RequireJS是一个很好的工具,可以解决一些非常重要的问题,并使我们开始朝着更具可扩展性,更专业化的Javascript应用程序迈进。 重要的是,这是许多人第一次遇到模块化和全球化的概念。 所以,如果你打算build立一个需要扩展的Javascript应用程序,那么Require和AMD模式并不是坏的工具。

但是, 有没有什么特别的Angular使得Require / AMD特别适合? 不,事实上,Angular为您提供了自己的模块化和封装模式,这在许多方面使得AMD的基本模块化特性变得冗余。 而且,将Angular模块集成到AMD模式中并不是不可能的,但是它有点…挑剔。 你一定会花时间把这两种模式整合起来。

对于Angular团队本身的一些观点,有来自Angular Batarang的作者Brian Ford,也是Angular核心团队的成员:

我不build议使用RequireJS和AngularJS。 虽然这当然是可能的,但我还没有看到RequireJS在实践中是有益的。

所以,在AngularJS这个非常具体的问题上:Angular和Require / AMD是正交的,并且在重叠的地方。 你可以一起使用它们,但是没有任何理由与Angular的本质/模式特别相关。

但是对于可伸缩的Javascript应用程序来说,内部和外部依赖的基本pipe理呢? 不需要在那里做一些非常重要的事情吗?

我build议检查Bower和NPM,尤其是NPM。 我并没有试图就这些工具的比较优势展开一场神圣的战争。 我只想说:还有其他的方法去处理这个猫,而这些方法可能比AMD / Require更好。 (2015年末,他们肯定有更多的人气,特别是NPM,加上ES6或CommonJS模块,请参阅相关的SO问题 。)

什么是懒加载?

请注意,延迟加载和延迟下载是不同的。 Angular的懒加载并不意味着你直接从服务器拉他们。 在使用javascript自动化的Yeoman风格的应用程序中,您将整个shebang连接成一个文件。 它们是存在的,但是没有被执行/实例化,直到需要。 通过这样做,速度和带宽的提高大大超过了从一个特定的20线控制器的懒惰下载所谓的改进。 实际上,该控制器浪费的networking延迟和传输开销将比控制器本身的大小大一个数量级。

但是,让我们假设你真的需要懒惰下载,也许你的应用程序不常用的部分,如pipe理界面。 这是一个非常合理的案例。 要求确实可以为你做到这一点。 但是也有很多 其他 可能 更 灵活的 选项可以完成同样的事情。 而Angular 2.0显然会为我们照顾这个,内置在路由器上 。 ( 详情 )

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

我怎么能得到所有我的数十/数百的脚本文件加载,而不需要手动将它们全部附加到index.html?

看一下Yeoman的generator-angular中的子生成器,或者generator- gulp -angular中的自动化模式,或者React的标准Webpack自动化。 这些为您提供了一个干净的,可扩展的方法,可以:在组件脚手架时自动附加文件,或者如果它们存在于特定的文件夹/匹配某些全局模式,就可以自动抓取所有文件。 一旦你有了后面的选项,你再也不需要考虑自己的脚本加载了。

底线?

需求是一个伟大的工具,对于某些事情。 但只要有可能,就尽可能地去吃谷物,尽可能分开你的顾虑。 让Angular担心Angular自己的模块化模式,并考虑使用ES6模块或CommonJS作为一般的模块化模式。 让现代自动化工具担心脚本加载和依赖pipe理。 并且细致地处理asynchronous延迟加载,而不是与另外两个问题纠缠在一起。

也就是说,如果您正在开发Angular应用程序,但由于某些原因无法在您的计算机上安装Node来使用Javascript自动化工具,那么Require可能是一个很好的替代解决scheme。 我已经看到了非常复杂的设置,人们希望dynamic加载Angular组件,每个组件声明自己的依赖关系或其他东西。 虽然我可能试图以另一种方式解决这个问题,但我可以看到这个想法的优点,就是那个特殊的情况。

但除此之外,当从头开始使用新的Angular应用程序和灵活性来创build一个现代化的自动化环境时,您有很多其他更灵活更现代化的select。

(重复更新以跟上不断变化的JS场景。)

是的,这是有道理的。

Angular模块不会尝试解决脚本加载sorting或延迟脚本获取的问题。 这些目标是正交的,两个模块系统可以并肩生活,并实现他们的目标。

来源: Angular JS官方网站

我相信这是一个主观的问题,所以我会提供我的主观意见。

Angular内置了模块化机制。当您创build应用程序时,您要做的第一件事就是

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

接着

 app.directive(...); app.controller(...); app.service(...); 

如果你看看angular度种子这是整齐的起始者应用程序的angular度,他们已经把指令,服务,控制器等分离到不同的模块,然后加载这些模块作为依赖在您的主要应用程序。

就像是 :

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

Angular也懒加载这些模块(到内存中)而不是它们的脚本文件。

就延迟加载脚本文件而言,要坦率地说,除非你写的东西非常大,否则将会是一个矫枉过正的问题,因为从本质上来说,angular度减less了你写的代码量。 如果写在angular度上,一个在大多数其他框架中编写的典型应用程序可能会减less大约30-50%的LOC。

对于AngularJS使用RequireJS是有道理的,但是只有当你了解它们是如何工作的dependency injection的时候 ,因为虽然它们都注入了依赖关系,但它们注入了非常不同的东西。

AngularJS有它自己的依赖系统,可以让你将AngularJS模块注入到新创build的模块中,以重用实现。 假设您创build了一个实现AngularJSfilter“迎接”的“第一个”模块:

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

现在让我们假设你想在另一个名为“second”的模块中使用“greet”filter来实现“再见”filter。 你可以这样做,注入“第一”模块到“第二”模块:

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

问题是,为了在没有RequireJS的情况下正常工作,在创build第二个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 + '!'; } }); }); 

您可以看到,在执行RequireJScallback的内容之前,我们依赖于要注入的“firstModule”文件,需要加载“第一个”AngularJS模块来创build“第二个”AngularJS模块。

注意:为了在RequireJScallback函数中使用AngularJS,需要在“firstModule”和“secondModule”文件中注入“angular”作为依赖关系,并且必须在RequireJS config上configuration它以将“angular”映射到库代码。 AngularJS也可以以传统的方式加载到页面(脚本标签),但是却要求RequireJS的好处。

更多关于从我的博客文章2.0版本的AngularJS核心RequireJS支持的细节。

基于我的博客文章“用AngularJS理解RequireJS” ,这里是链接 。

正如@ganaraj所提到的,AngularJS的核心是dependency injection。 在使用和不使用RequireJS的情况下构build玩具种子应用程序时,我个人发现RequireJS对于大多数使用情况可能是过度的。

这并不意味着RequireJS对于脚本加载function没有用,并且在开发过程中保持代码清理。 结合r.js优化器( https://github.com/jrburke/r.js )和almond( https://github.com/jrburke/almond )可以创build一个非常苗条的脚本加载故事。 然而,由于它的依赖pipe理特性对于应用程序核心来说并不重要,您还可以评估其他客户端(HeadJS,LABjs,…)甚至服务器端(MVC4 Bundler,…)脚本加载解决scheme为您的特定应用程序。

是的,特别是对于非常大的SPA。

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

但是,AngularJS和RequireJS的集成有点棘手。 我创build了angularAMD,使其成为一个不那么痛苦的过程:

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

简单的答案是,这是有道理的。 最近在ng-conf 2014中对此进行了讨论。以下是关于此主题的讨论:

http://www.youtube.com/watch?v=4yulGISBF8w

如果你计划在懒惰的加载控制器和指令等,同时也将多个懒惰的依赖关系组合成单个脚本文件,以便更快的延迟加载,那么使用requirejs和angularjs是有意义的。 RequireJS有一个优化工具 ,使组合变得容易。 见http://ify.io/using-requirejs-with-optimisation-for-lazy-loading-angularjs-artefacts/

是的,在Angular上使用requireJS是有意义的,我花了好几天的时间来testing几个技术scheme。

我在服务器端用RequireJS做了一个Angular Seed。 很简单的一个。 我使用SHIM标记不使用AMD模块,也不使用AMD,因为我认为处理两种不同的Dependency注入系统是非常困难的。

我使用grunt和r.js连接服务器上的js文件取决于SHIMconfiguration(依赖项)文件。 所以我只在我的应用程序中引用一个js文件。

欲了解更多信息去我的githubangular种子: https : //github.com/matohawk/angular-seed-requirejs

我会避免使用Require.js。 我已经看到的应用程序,结束了多种types的模块模式架构。 AMD,揭示,IIFE的不同口味等。还有其他方式来加载需求,如loadOnDemand Angular mod 。 添加其他的东西只是填充你的代码充满cruft和创build一个低信噪比 ,使您的代码难以阅读。

以下是我使用的方法: http : //thaiat.github.io/blog/2014/02/26/angularjs-and-requirejs-for-very-large-applications/

该页面显示了AngularJS + RequireJS的一个可能的实现,其中代码按照要素分割,然后是组件types。

布莱恩·福特的回答

AngularJS有自己的模块系统,通常不需要像RJS这样的东西。

参考: https : //github.com/yeoman/generator-angular/issues/40

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

但万一你的项目变大了 或者你预期这种情况,你应该整合angularj和requirejs。 在这篇文章中,你可以看到这样的集成的演示应用程序。