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


当前回答

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

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

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

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”,这里有一个链接。

布莱恩·福特的回答

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

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

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

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

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

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

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

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。

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