我是 Angular.js 的新手,并试图了解它与 Backbone.js 的不同之处......我们曾经在使用 Backbone 时使用 Require.js 管理我们的包依赖项。对 Angular.js 做同样的事情有意义吗?
14 回答
是的,与可用于模块化组件的 whereangular.js
一起使用是有意义的。require.js
require.js
有一个种子项目使用both angular.js and require.js
.
重申我认为OP的问题确实是:
如果我主要在 Angular 1.x 中构建应用程序,并且(隐式)在 Grunt/Gulp/Broccoli 和 Bower/NPM 时代这样做,并且我可能有几个额外的库依赖项,是否需要添加清晰、具体价值超出了我使用 Angular 而没有 Require 所获得的价值?
或者,换一种说法:
“如果我有其他处理基本脚本加载的方法,香草 Angular 是否需要 Require 来有效管理基本 Angular 组件加载? ”
我相信对此的基本答案是:“除非你有其他事情发生,和/或你无法使用更新、更现代的工具,否则不会。”
首先让我们明确一点:RequireJS 是一个伟大的工具,它解决了一些非常重要的问题,并开始了我们正在走的道路,朝着更可扩展、更专业的 Javascript 应用程序迈进。重要的是,这是许多人第一次遇到模块化和使事物脱离全局范围的概念。因此,如果您要构建一个需要扩展的 Javascript 应用程序,那么 Require 和 AMD 模式对于这样做来说是不错的工具。
但是,Angular 有什么特别之处可以让 Require/AMD 特别适合吗?不。事实上,Angular 为您提供了自己的模块化和封装模式,这在许多方面使 AMD 的基本模块化特性变得多余。而且,将 Angular 模块集成到 AMD 模式中并非不可能,但它有点……挑剔。您肯定会花时间让这两种模式很好地集成。
对于 Angular 团队本身的一些观点,这是来自 Angular Batarang 的作者,现在是 Angular 核心团队成员的 Brian Ford 的观点:
我不建议将 RequireJS 与 AngularJS 一起使用。虽然这当然是可能的,但我还没有看到任何 RequireJS 在实践中有益的例子。
因此,关于 AngularJS 的一个非常具体的问题:Angular 和 Require/AMD 是正交的,并且在某些地方重叠。您可以一起使用它们,但没有理由与 Angular 本身的性质/模式特别相关。
但是对于可扩展的 Javascript 应用程序的内部和外部依赖项的基本管理呢?不需要在那里做一些对我来说非常重要的事情吗?
我建议查看 Bower 和 NPM,尤其是 NPM。我并不是要就这些工具的相对优势发起一场圣战。我只想说:还有其他方法可以给猫剥皮,这些方法可能比 AMD/Require 更好。(它们在 2015 年末肯定有更受欢迎的势头,尤其是 NPM,结合 ES6 或 CommonJS 模块。请参阅相关的 SO 问题。)
延迟加载呢?
请注意,延迟加载和延迟下载是不同的。Angular 的延迟加载并不意味着你直接从服务器中拉取它们。在带有 javascript 自动化的 Yeoman 风格的应用程序中,您将整个 shebang 连接并缩小到一个文件中。它们存在,但直到需要时才执行/实例化。这样做所带来的速度和带宽改进大大超过了延迟下载特定的 20 线控制器所带来的任何所谓的改进。事实上,该控制器浪费的网络延迟和传输开销将比控制器本身的大小大一个数量级。
但是假设您确实需要延迟下载,也许是针对您的应用程序中不经常使用的部分,例如管理界面。这是一个非常正当的案例。Require 确实可以为您做到这一点。但是还有许多其他可能更 灵活的选项可以完成同样的事情。Angular 2.0 显然会为我们解决这个问题,内置于router中。(详情。)
但是在我的本地 dev boxen 的开发过程中呢?
如何在不需要手动将它们全部附加到 index.html 的情况下加载所有数十个/数百个脚本文件?
看看 Yeoman 的 generator-angular 中的子生成器,或者generator-gulp-angular中体现的自动化模式,或者 React 的标准 Webpack 自动化。这些为您提供了一种干净、可扩展的方式:在构建组件时自动附加文件,或者如果它们存在于某些文件夹中/匹配某些 glob 模式,则简单地自动获取它们。一旦有了后一种选择,您就再也不需要考虑自己的脚本加载了。
底线?
对于某些事情,Require 是一个很好的工具。但尽可能随心所欲,并尽可能分离你的关注点。让 Angular 担心 Angular 自己的模块化模式,考虑使用 ES6 模块或 CommonJS 作为通用模块化模式。让现代自动化工具担心脚本加载和依赖管理。并以细粒度的方式处理异步延迟加载,而不是将其与其他两个问题纠缠在一起。
也就是说,如果您正在开发 Angular 应用程序,但由于某种原因无法在您的机器上安装 Node 以使用 Javascript 自动化工具,那么 Require 可能是一个很好的替代解决方案。而且我已经看到了非常复杂的设置,人们希望动态加载每个声明自己的依赖项或其他东西的 Angular 组件。虽然我可能会尝试以另一种方式解决这个问题,但对于那种非常特殊的情况,我可以看到这个想法的优点。
但除此之外......当从头开始使用新的 Angular 应用程序和创建现代自动化环境的灵活性......你有很多其他的、更灵活、更现代的选择。
(不断更新以跟上不断发展的 JS 场景。)
是的,这是有道理的。
Angular 模块不会尝试解决脚本加载顺序或延迟脚本获取的问题。这些目标是正交的,两个模块系统可以并存并实现它们的目标。
来源:Angular JS官网
This I believe is a subjective question, so I will provide my subjective opinion.
Angular has a modularization mechanism built in. When you create your app, the first thing you would do is
var app = angular.module("myApp");
and then
app.directive(...);
app.controller(...);
app.service(...);
If you have a look at the angular-seed which is neat starter app for angular, they have separated out the directives, services, controllers etc into different modules and then loaded those modules as dependancies on your main app.
Something like :
var app = angular.module("myApp",["Directives","Controllers","Services"];
Angular also lazy loads these modules ( into memory) not their script files.
In terms of lazy loading script files, to be frank unless you are writing something extremely large it would be an overkill because angular by its very nature reduces the amount of code you write. A typical app written in most other frameworks could expect a reduction in around 30-50% in LOC if written in angular.
将 RequireJS 与 AngularJS 一起使用是有意义的,但前提是您了解它们各自在依赖注入方面的工作方式,因为尽管它们都注入依赖项,但它们注入的东西却截然不同。
AngularJS 有自己的依赖系统,可以让你将 AngularJS 模块注入到新创建的模块中,以便重用实现。假设您创建了一个实现 AngularJS 过滤器“greet”的“第一个”模块:
angular
.module('first', [])
.filter('greet', function() {
return function(name) {
return 'Hello, ' + name + '!';
}
});
现在假设您想在另一个名为“second”的模块中使用“greet”过滤器,该模块实现了“goodbye”过滤器。您可以将“第一个”模块注入“第二个”模块:
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”映射到库代码。您可能也以传统方式(脚本标记)将 AngularJS 加载到页面,尽管这会破坏 RequireJS 的好处。
更多关于从我的博客文章 2.0 版本的 AngularJS 核心获得 RequireJS 支持的详细信息。
根据我的博文“用 AngularJS 理解 RequireJS”,这里是链接。
正如@ganaraj 提到的,AngularJS 的核心是依赖注入。在使用和不使用 RequireJS 构建玩具种子应用程序时,我个人发现 RequireJS 对于大多数用例来说可能是多余的。
这并不意味着 RequireJS 对它的脚本加载功能和在开发过程中保持代码库的清洁没有用处。将 r.js 优化器 ( https://github.com/jrburke/r.js ) 与almond ( https://github.com/jrburke/almond ) 相结合可以创建一个非常精简的脚本加载故事。但是,由于它的依赖管理功能在应用程序核心中的 Angular 并不重要,因此您还可以评估其他客户端(HeadJS、LABjs、...)甚至服务器端(MVC4 Bundler、...)脚本加载解决方案为您的特定应用程序。
是的,它确实如此,特别是对于非常大的 SPA。
在某些情况下,RequireJS 是必须的。例如,我使用同样使用 Google Map API 的 AngularJS 开发 PhoneGap 应用程序。如果没有像 RequireJS 这样的 AMD 加载程序,应用程序在离线时启动时会简单地崩溃,因为它无法获取 Google Map API 脚本。AMD 加载程序让我有机会向用户显示错误消息。
但是,AngularJS 和 RequireJS 之间的集成有点棘手。我创建了 angularAMD 来让这个过程变得不那么痛苦:
Short answer is, it make sense. Recently this was discussed in ng-conf 2014. Here is the talk on this topic:
如果您计划延迟加载控制器和指令等,则将 requirejs 与 angularjs 一起使用是有意义的,同时还将多个延迟依赖项组合到单个脚本文件中以更快地延迟加载。RequireJS 有一个优化工具,使组合变得容易。请参阅http://ify.io/using-requirejs-with-optimisation-for-lazy-loading-angularjs-artefacts/
是的,将 requireJS 与 Angular 一起使用是有意义的,我花了几天时间测试了几种技术解决方案。
我在服务器端使用 RequireJS 制作了一个 Angular 种子。很简单的一个。我对没有 AMD 模块而不是 AMD 使用 SHIM 表示法,因为我认为处理两个不同的依赖注入系统非常困难。
我使用 grunt 和 r.js 连接服务器上的 js 文件取决于 SHIM 配置(依赖)文件。所以我在我的应用程序中只引用了一个 js 文件。
有关更多信息,请访问我的 github Angular Seed: https ://github.com/matohawk/angular-seed-requirejs
我会避免使用 Require.js。我见过的应用程序会导致多种类型的模块模式架构混乱。AMD、Revealing、不同风格的 IIFE 等。还有其他按需加载的方法,例如loadOnDemand Angular mod。添加其他内容只会使您的代码充满杂乱无章,并导致低信噪比并使您的代码难以阅读。
这是我使用的方法:http: //thaiat.github.io/blog/2014/02/26/angularjs-and-requirejs-for-very-large-applications/
该页面显示了 AngularJS + RequireJS 的可能实现,其中代码按功能拆分,然后按组件类型拆分。
布赖恩福特的回答
AngularJS 有它自己的模块系统,通常不需要像 RJS 这样的东西。
我认为这取决于您的项目复杂性,因为 Angular 几乎是模块化的。您的控制器可以被映射,您只需在 index.html 页面中导入这些 JavaScript 类。
但是如果你的项目变得更大。或者您预计到这种情况,您应该将 Angular 与 requirejs 集成。在本文中,您可以看到用于此类集成的演示应用程序。