在Angular.js中使用Require.js有意义吗?

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

160878 次浏览

是的,使用angular.jsrequire.js一起使用是有意义的,其中你可以使用require.js来模块化组件

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

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

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

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

然后

app.directive(...);


app.controller(...);


app.service(...);

如果你看一下angular-seed,它是angular的入门级应用,它将指令、服务、控制器等分离到不同的模块中,然后将这些模块作为依赖项加载到你的主应用中。

比如:

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

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

至于延迟加载脚本文件,坦率地说,除非你写的是非常大的东西,否则它会是一个过度的,因为angular本质上减少了你编写的代码量。在大多数其他框架中编写的典型应用,如果用angular编写,可以减少大约30-50%的LOC。

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

这并不意味着RequireJS在脚本加载功能和在开发过程中保持代码库整洁方面没有用处。结合r.js优化器(https://github.com/jrburke/r.js)和almond (https://github.com/jrburke/almond)可以创建一个非常简洁的脚本加载故事。然而,由于它的依赖管理特性在你的应用程序的核心中并不那么重要,你也可以为你的特定应用程序评估其他客户端(HeadJS, LABjs,…)甚至服务器端(MVC4 Bundler,…)脚本加载解决方案。

是的,这很有道理。

Angular模块不会尝试解决脚本加载顺序的问题 或者惰性脚本抓取。这些目标是正交的,都是模块 系统可以共存并实现各自的目标。

来源:Angular JS官网 . com

是的,在Angular中使用requireJS是有意义的,我花了几天时间来测试几个技术解决方案。

我在服务器端用RequireJS做了一个Angular种子。非常简单。 我使用SHIM符号表示没有AMD模块和没有AMD,因为我认为处理两个不同的依赖注入系统非常困难。< / p >

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

更多信息请访问我的github Angular Seed: https://github.com/matohawk/angular-seed-requirejs < / p >

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

重申一下我认为OP的问题真正是什么:

如果我主要用Angular 1构建应用程序。在Grunt/Gulp/Broccoli和Bower/NPM时代(隐式地)这样做,并且我可能有一些额外的库依赖,Require是否比我使用Angular不使用Require所获得的价值更清晰、更具体?

或者换句话说:

“普通Angular是否需要Require来有效地管理基本的Angular组件加载,如果我有其他方式处理基本的脚本加载?

我相信最基本的答案是:“除非你有别的事情要做,或者你不能使用更新、更现代的工具。”

让我们从一开始就明确一点:RequireJS是一个很棒的工具,它解决了一些非常重要的问题,并让我们走上了一条更可伸缩、更专业的Javascript应用程序的道路。重要的是,这是许多人第一次接触到模块化的概念以及将事物从全局范围中解脱出来的概念。如果你要构建一个需要伸缩的Javascript应用,Require和AMD模式都是不错的工具。

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

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

我不推荐AngularJS使用RequireJS。虽然这当然是可能的,但我还没有看到RequireJS在实践中有任何好处的实例。

所以,关于AngularJS这个非常具体的问题:Angular和Require/AMD是正交的,在某些地方是重叠的。你可以将它们一起使用,但这与Angular本身的性质/模式没有特别的关系。

但是如何对可伸缩Javascript应用程序的内部和外部依赖关系进行基本管理呢?难道Require没有为我做一些非常重要的事情吗?

我建议你看看Bower和NPM,尤其是NPM。我并不是要开始一场关于这些工具的相对好处的圣战。我只是想说:还有其他方法来剥那只猫的皮,这些方法五月甚至比AMD/Require更好。(它们在2015年末肯定会更受欢迎,特别是NPM,结合ES6或CommonJS模块。参见相关SO问题)。

那么惰性加载呢?

注意,惰性加载和惰性下载是不同的。Angular的惰性加载并不意味着你要直接从服务器上获取它们。在带有javascript自动化的yeoman风格的应用程序中,您将整个程序连接并缩小到单个文件中。它们存在,但直到需要时才执行/实例化。这样做所带来的速度和带宽提升大大超过了延迟下载特定的20线控制器所带来的所谓提升。事实上,该控制器所浪费的网络延迟和传输开销将比控制器本身的大小大一个数量级。

但是,假设您确实需要惰性下载,也许是应用程序中不经常使用的部分,比如管理界面。这是一个非常合理的案例。Require确实可以为你做到这一点。但是有 许多 其他潜在的 更多的 灵活的 选项完成同样的事情。Angular 2.0显然会帮我们解决这个问题,内置在路由器中。(细节)。

但是在我的本地开发boxen上进行开发时呢?

我如何才能得到我所有的几十/数百个脚本文件加载,而不需要将它们都附加到index.html手动?

看看Yeoman的generator-angular中的子生成器,或者generator-gulp-angular中包含的自动化模式,或者React的标准Webpack自动化。这为您提供了一种干净的、可伸缩的方式:在构建组件时自动附加文件,或者在组件存在于特定文件夹/匹配特定glob-pattern时自动抓取所有文件。一旦有了后一种选项,就再也不需要考虑自己的脚本加载了。

底线?

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

也就是说,如果你正在开发Angular应用,但由于某些原因不能在你的机器上安装Node来使用Javascript自动化工具,那么Require可能是一个很好的替代解决方案。我也见过一些非常复杂的设置,人们想动态加载Angular组件,每个组件都声明了自己的依赖项之类的。虽然我可能会尝试用另一种方式解决这个问题,但我可以看到这个想法的优点,在这种非常特殊的情况下。

但除此之外……当你从头开始创建一个新的Angular应用程序,并灵活地创建一个现代自动化环境时……你还有很多其他更灵活、更现代的选择。

(不断更新,以跟上不断发展的JS场景。)

我认为这取决于你的项目复杂程度,因为angular是相当模块化的。 你的控制器可以被映射,你可以在index.html页面中导入那些JavaScript类。< / p >

但万一你的项目变大了。或者你预料到了这样的场景,你应该把angular和requirejs集成在一起。在文章中,你可以看到这样一个集成的演示应用程序。

我会避免使用Require.js。我所见过的这样做的应用程序最终会把多种类型的模块模式架构弄得一团糟。AMD, reveal,不同口味的IIFE等。还有其他方法可以按需加载,比如Angular mod。添加其他东西只会让你的代码充满cruft,并创建低信噪比,使你的代码难以阅读。

是的,专门为大型SPA服务。

在某些场景中,RequireJS是必须的。例如,我使用AngularJS开发PhoneGap应用程序,它也使用谷歌Map API。如果没有像RequireJS这样的AMD加载器,应用程序只会在离线时启动时崩溃,因为它不能来源谷歌地图API脚本。AMD加载器让我有机会向用户显示错误消息。

然而,AngularJS和RequireJS之间的集成有点棘手。我创建了angularAMD,使这个过程不那么痛苦:

< a href = " http://marcoslin.github。io / angularAMD noreferrer“rel = > http://marcoslin.github.io/angularAMD/ < / >

在AngularJS中使用RequireJS是有意义的,但前提是你必须理解它们在依赖注入中的工作方式,因为尽管它们都注入依赖关系,但它们注入的东西非常不同。

AngularJS有自己的依赖系统,它允许你将AngularJS模块注入到新创建的模块中,以便重用实现。假设你创建了一个"first"模块,它实现了AngularJS过滤器"greet":

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

现在假设你想在另一个叫做“second”的模块中使用“greet”过滤器,这个模块实现了一个“goodbye”过滤器。你可以把"first"模块注入到"second"模块:

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模块。

边注:在“firstModule”和“secondModule”文件中注入“angular”,作为在RequireJS回调函数中使用AngularJS的依赖项,它必须在RequireJS配置中配置,以将“angular”映射到库代码中。你也可以用传统的方式(script标签)将AngularJS加载到页面中,尽管这与RequireJS的优点相违背。

更多关于AngularJS 2.0内核支持RequireJS的细节,请见我的博文。

根据我的博客文章“用AngularJS制作RequireJS的意义”,这里是链接

简单地说,这是有道理的。最近,ng-conf 2014讨论了这个问题。下面是关于这个话题的演讲:

http://www.youtube.com/watch?v=4yulGISBF8w < a href = " http://www.youtube.com/watch?v=4yulGISBF8w " > < / >

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

该页面显示了AngularJS + RequireJS的可能实现,其中代码按特性和组件类型分开。

布莱恩·福特的回答

AngularJS有自己的模块系统,通常不需要RJS之类的东西。

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