关于javascript:将Require.js与Angular.js一起使用是否有意义?

Does it make sense to use Require.js with Angular.js?

我是angular.js的新手,想了解它和主干有什么不同。在使用主干时,我们使用require.js来管理包依赖性。对angular.js也这样做有意义吗?


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

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


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

If I'm building an application principally in Angular 1.x, and (implicitly) doing so in the era of Grunt/Gulp/Broccoli and Bower/NPM, and I maybe have a couple additional library dependencies, does Require add clear, specific value beyond what I get by using Angular without Require?

Ok.

或者换个说法:好的。

"Does vanilla Angular need Require to manage basic Angular component-loading effectively, if I have other ways of handling basic script-loading?"

Ok.

我认为最基本的答案是:"除非你有别的事情发生,或者你不能使用更新的,更现代的工具。"好的。

首先,我们要明确一点:RequireJS是一个很好的工具,它解决了一些非常重要的问题,并使我们沿着我们所处的道路前进,朝着更可扩展、更专业的JavaScript应用程序前进。重要的是,这是许多人第一次遇到模块化的概念,并使事情走出全球范围。因此,如果您要构建一个需要扩展的JavaScript应用程序,那么Require和AMD模式都是不错的工具。好的。

但是,有没有什么特别的角度,使需要/和一个特别好的适合?不,事实上,Angular为您提供了自己的模块化和封装模式,这在很多方面使AMD的基本模块化功能变得多余。而且,将角模块集成到AMD模式中并非不可能,但这有点…挑剔的您肯定会花时间让这两个模式完美地集成。好的。

For some perspective from the Angular team itself, there's this, from Brian Ford, author of the Angular Batarang and now a member of the Angular core team:好的。

I don't recommend using RequireJS with AngularJS. Although it's certainly possible, I haven't seen any instance where RequireJS was beneficial in practice.

Ok.

因此,在AngularJS的一个非常具体的问题上:角度和需求/AMD是正交的,并且在某些地方是重叠的。你可以一起使用它们,但是没有任何理由专门与角本身的性质/模式相关。好的。但是,对于可伸缩的JavaScript应用程序,内部和外部依赖关系的基本管理如何呢?不需要做一些对我来说非常重要的事情吗?

我建议去看看鲍尔和NPM,尤其是NPM。我并不是要为这些工具的相对利益发动一场神圣的战争。我只想说:还有其他的方法可以剥那只猫的皮,而且这些方法可能比AMD/要求的更好。(它们在2015年下半年肯定有更为流行的势头,尤其是NPM,结合ES6或CommonJS模块。参见相关的销售订单问题。)好的。懒惰的装载怎么办?

注意,延迟加载和延迟下载是不同的。Angular的延迟加载并不意味着你直接从服务器上拉它们。在一个具有Javascript自动化的约曼风格的应用程序中,您将把整个shebang连接在一起并缩小为一个文件。它们存在,但需要时才执行/实例化。从这项工作中获得的速度和带宽改进远远超过了所谓的延迟下载特定20线控制器的改进。实际上,该控制器浪费的网络延迟和传输开销将比控制器本身的大小大一个数量级。好的。

但是,假设您确实需要延迟下载,也许对于应用程序中不经常使用的部分,比如管理界面。这是一个非常合理的案例。需求确实能为你做到这一点。但是也有许多其他的,可能更灵活的选择来完成同样的事情。而Angular2.0显然会为我们解决这个问题,内置于路由器中。(详情)好的。但是在开发我的本地dev boxen的过程中呢?

如何在不需要手动将数十个/数百个脚本文件全部附加到index.html的情况下加载它们?好的。

看看约曼发电机角的子发电机,或发电机谷角的自动化模式,或标准的Webpack Automation for React。这些为您提供了一种干净的、可扩展的方法:在组件架起时自动附加文件,或者在某些文件夹中存在/匹配某些全局模式时自动获取所有文件。一旦有了后一个选项,就再也不需要考虑自己的脚本加载了。好的。底线?

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

也就是说,如果您正在开发Angular应用程序,但由于某种原因无法在您的机器上安装节点来使用JavaScript自动化工具,那么Require可能是一个不错的替代解决方案。我看到了非常复杂的设置,人们希望动态加载角度组件,每个组件都声明自己的依赖性或其他东西。虽然我可能会尝试用另一种方法来解决这个问题,但我可以看到这个想法的优点,对于那个非常特殊的情况。好的。

但如果……当一个新的角从划痕和灵活的应用程序创建一个现代的自动化环境。你已经有很多其他的,更灵活,更现代的选项。

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

好的。


是的,这是有道理的。

Angular modules don't try to solve the problem of script load ordering
or lazy script fetching. These goals are orthogonal and both module
systems can live side by side and fulfil their goals.

Source: Angular JS official website


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

Angular内置模块化机制。创建应用程序时,首先要做的是

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

然后

1
2
3
4
5
app.directive(...);

app.controller(...);

app.service(...);

如果你看一下Angular Seed,它是Angular的入门级应用程序,它们将指令、服务、控制器等分离成不同的模块,然后根据你的主应用程序加载这些模块。

比如:

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

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

对于延迟加载脚本文件而言,坦率地说,除非您正在编写非常大的内容,否则这将是一种过度杀伤力,因为从本质上讲,Angular减少了您编写的代码量。在大多数其他框架中编写的典型应用程序,如果以角度编写,那么loc中的值可能会减少大约30-50%。


在AngularJS中使用RequireJS是有意义的,但是只有当您了解它们中的每一个在依赖注入方面是如何工作的,就像它们都注入依赖一样,它们注入了非常不同的东西。

AngularJS has its own dependency system that let you inject AngularJS modules to a newly created module in order to reuse implementations. 假设您创建了一个实现AngularJS过滤器"Greet"的"First"模块:

1
2
3
4
5
6
7
angular
  .module('first', [])
  .filter('greet', function() {
    return function(name) {
      return 'Hello, ' + name + '!';
    }
  });

现在假设您想在另一个名为"second"的模块中使用"greet"过滤器,该模块实现"再见"过滤器。您可以将"第一"模块注入"第二"模块:

1
2
3
4
5
6
7
angular
  .module('second', ['first'])
  .filter('goodbye', function() {
    return function(name) {
      return 'Good bye, ' + name + '!';
    }
  });

问题是,为了在不需要的情况下正确地工作,在创建"第二个"AngularJS模块之前,必须确保页面上加载了"第一个"AngularJS模块。报价文件:

Depending on a module implies that required module needs to be loaded
before the requiring module is loaded.

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

回到"第一个"和"第二个"AngularJS模块,下面介绍如何使用RequireJS将不同文件上的模块分离,以利用脚本依赖项加载:

1
2
3
4
5
6
7
8
9
10
// firstModule.js file
define(['angular'], function(angular) {
  angular
    .module('first', [])
    .filter('greet', function() {
      return function(name) {
        return 'Hello, ' + name + '!';
      }
    });
});
1
2
3
4
5
6
7
8
9
10
// secondModule.js file
define(['angular', 'firstModule'], function(angular) {
  angular
    .module('second', ['first'])
    .filter('goodbye', function() {
      return function(name) {
        return 'Good bye, ' + name + '!';
      }
    });
});

您可以看到,在执行RequireJS回调的内容之前,我们依赖于要注入的"FirstModule"文件,这需要加载"First"AngularJS模块来创建"Second"AngularJS模块。

侧注:为了在RequireJS回调函数中使用AngularJS,需要在"FirstModule"和"SecondModule"文件中插入"Angular",并且必须在RequireJS配置中配置它,以将"Angular"映射到库代码。您也可以用传统的方式(脚本标记)将AngularJS加载到页面中,尽管失败会带来好处。

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

基于我的博客文章"了解安古拉吉斯的需求",这里是链接。


正如@ganaraj所提到的,angularjs的核心是依赖注入。当构建带有或不带有RequireJS的玩具种子应用程序时,我个人发现RequireJS对于大多数用例来说可能是杀伤力过大的。

这并不意味着RequireJS对于它的脚本加载功能和在开发过程中保持代码库的整洁没有用处。将r.js优化器(https://github.com/jrburke/r.js)与almond(https://github.com/jrburke/almond)结合在一起可以创建一个非常纤细的脚本加载故事。但是,由于它的依赖性管理功能在应用程序核心的角度上没有那么重要,因此您还可以为特定应用程序评估其他客户端(headjs、labjs,…)甚至服务器端(mvc4 bundler,…)脚本加载解决方案。


是的,是的,特别是大型水疗中心。

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

然而,AngularJS和RequireJS之间的集成有点棘手。我创造了安古拉兰德,使这个过程不那么痛苦:

http://marcslin.github.io/angularamd/


简短的回答是,这是有道理的。最近在2014年国家会议上讨论了这一点。下面是关于这个主题的讨论:

http://www.youtube.com/watch?V= 4YulgISBF8W


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


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

我在服务器端用Requirejs生成了一个有棱角的种子。非常简单。我使用填充符号表示没有AMD模块,而不是AMD,因为我认为很难处理两个不同的依赖注入系统。

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

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


我会避免使用require.js。我见过这样做的应用程序最终导致了多种类型的模块模式体系结构的混乱。AMD,透露,不同口味的iife等。有其他方式加载按需,如加载和角度mod。添加其他东西只会使代码充满污点,并产生低信噪比,使代码难以读取。


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

该页显示了AngularJS+RequireJS的可能实现,其中代码按功能和组件类型进行拆分。


布莱恩·福特的回答

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

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


我认为这取决于您的项目复杂性,因为角度是相当模块化的。Your controllers can be mapped and you can just import those JavaScript classes in your index.html page.

但万一你的项目变得更大。或者您预期这样的场景,您应该将角度与需求集成在一起。在本文中,您可以看到用于这种集成的演示应用程序。