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

时间:2012-09-21 10:49:39

标签: javascript requirejs angularjs

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

14 个答案:

答案 0 :(得分:223)

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

我可以指向使用both angular.js and require.js的{​​{3}}。希望有所帮助!

答案 1 :(得分:151)

重申我认为OP的问题的真正含义:

  

如果我主要在Angular 1.x中构建一个应用程序,并且(隐含地)在Grunt / Gulp / Broccoli和Bower / NPM时代这样做,并且我可能还有一些额外的库依赖项,那么需要添加明确的,特定的值超出我使用Angular而不需要吗?

或者,换句话说:

  

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

我相信基本的答案是:"除非您有其他事情发生,否则/或者您无法使用更新,更现代的工具。&#34 ;

让我们从一开始就明白:RequireJS是一个很好的工具,可以解决一些非常重要的问题,让我们开始走向更加可扩展,更专业的Javascript应用程序。重要的是,这是许多人第一次遇到模块化的概念,并使事物脱离全球范围。所以,如果你要构建一个需要扩展的Javascript应用程序,那么Require和AMD模式就不是那么糟糕的工具。

但是, Angular有什么特别的东西让Require / AMD特别适合吗?没有。实际上,Angular为您提供了自己的模块化和封装模式,它在很多方面呈现冗余AMD的基本模块化特征。并且,将Angular模块集成到AMD模式中并非不可能,但它有点......挑剔。你肯定会花时间让这两种模式很好地整合。

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

  

我不建议将RequireJS与AngularJS一起使用。虽然这当然是可能的,但我还没有看到任何需要在实践中有益的实例。

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

但是可伸缩Javascript应用程序的内部和外部依赖关系的基本管理呢?不要求在那里做一些对我很重要的事情吗?

我建议查看Bower和NPM,特别是NPM。我并没有试图就这些工具的相对好处展开一场神圣的战争。我只是想说:还有其他方法可以让那只猫受到伤害,那些可能甚至比AMD / Require更好。 (他们肯定会在2015年末更受欢迎,尤其是NPM,结合ES6或CommonJS模块。请参阅related SO question

延迟加载怎么办?

请注意,延迟加载和延迟下载是不同的。 Angular的延迟加载并不意味着您直接从服务器中提取它们。在具有javascript自动化功能的Yeoman风格的应用程序中,您将整个shebang连接并缩小为一个文件。它们会出现,但在需要之前不会执行/实例化。从这样做中获得的速度和带宽改进大大超过了懒惰下载特定20行控制器所带来的任何改进。事实上,该控制器浪费的网络延迟和传输开销将比控制器本身的大小大一个数量级。

但是,让我们说你真的需要懒惰下载,也许是因为你的应用程序不经常使用的部分,比如管理界面。这是一个非常合理的案例。要求确实可以为你做到这一点。但also many otherpotentially more flexible options可以完成同样的事情。 Angular 2.0显然会为我们处理这个问题,内置于router。 (Details。)

但是在开发我的本地开发盒时呢?

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

查看Yeoman的generator-angular中的子生成器,或generator-gulp-angular中体现的自动化模式,或React的标准Webpack自动化。它们为您提供了一种干净,可扩展的方式:在组件构建时自动附加文件,或者如果它们存在于某些文件夹中/匹配某些glob模式,则只需自动将它们全部抓取。一旦你获得了后一种选择,你再也不需要考虑自己的脚本加载了。

底线?

对于某些事情,需求是一个很好的工具。但是尽可能使用谷物,并尽可能分开您的顾虑。让Angular担心Angular自己的模块化模式,并考虑使用ES6模块或CommonJS作为一般的模块化模式。让现代自动化工具担心脚本加载和依赖管理。并以细粒度的方式处理异步延迟加载,而不是将其与其他两个问题纠缠在一起。

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

但是否则......当从头开始使用新的Angular应用程序并灵活地创建现代自动化环境时......您已经拥有了许多其他更灵活,更现代的选项。

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

答案 2 :(得分:135)

是的,这很有道理。

  

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

     

来源:Angular JS official website

答案 3 :(得分:57)

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

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

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

然后

app.directive(...);

app.controller(...);

app.service(...);

如果你看一下angular-seed是一个整洁的启动应用程序的角度,它们已经将指令,服务,控制器等分离到不同的模块中,然后将这些模块作为依赖项加载到你的主应用程序上。

类似的东西:

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

Angular也懒得加载这些模块(进入内存)而不是他们的脚本文件。

就延迟加载脚本文件而言,坦率地说,除非你写的东西非常大,否则会有点过分,因为角度本质上减少了你编写的代码量。如果以角度编写,在大多数其他框架中编写的典型应用程序可以预期在LOC中减少约30-50%。

答案 4 :(得分: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配置上配置它以将“angular”映射到图书馆代码。你也可以用传统的方式将AngularJS加载到页面(脚本标记),尽管会损害RequireJS的好处。

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

根据我的博客帖子“了解使用AngularJS的RequireJS”,这里是link

答案 5 :(得分:21)

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

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

答案 6 :(得分:17)

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

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

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

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

答案 7 :(得分:12)

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

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

答案 8 :(得分:7)

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

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

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

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

答案 9 :(得分:7)

如果你计划延迟加载控制器和指令等,使用requirejs和angularjs是有意义的,同时还将多个惰性依赖项组合到单个脚本文件中,以便更快地加载延迟。 RequireJS有一个optimisation tool,使组合变得容易。见http://ify.io/using-requirejs-with-optimisation-for-lazy-loading-angularjs-artefacts/

答案 10 :(得分:3)

我会避免使用Require.js。我见过的应用程序可以解决多种类型的模块模式架构。 AMD,Revealing,不同风格的IIFE等。还有其他方式可以按需加载loadOnDemand Angular mod。添加其他内容只会使您的代码充满残余并创建low signal to noise ratio并使您的代码难以阅读。

答案 11 :(得分:2)

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

该页面显示了AngularJS + RequireJS的可能实现,其中代码按功能分割,然后按组件类型分割。

答案 12 :(得分:1)

Brian Ford的回答

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

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

答案 13 :(得分:0)

我认为这取决于你的项目复杂性,因为角度非常模块化。 您的控制器可以映射,您只需在index.html页面中导入这些JavaScript类。

但是如果你的项目变大了。或者你预计这种情况,你应该将angular与requirejs集成。在this文章中,您可以看到用于此类集成的演示应用。