首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

AMD最终揭秘

2012-09-12 
AMD终极揭秘原文: http://www.sitepen.com/blog/2012/06/25/amd-the-definitive-source/作者:Kris Zyp译者

AMD终极揭秘

原文: http://www.sitepen.com/blog/2012/06/25/amd-the-definitive-source/

作者:Kris Zyp

译者:Elaine Liu

究竟什么是AMD?

随着web应用不断发展和对JavaScript依赖的进一步加深,出现了使用模块(Modules)来组织代码和依赖性。模块使得我们创建明确清晰的组件和接口,这些组件和接口能够很容易的加载并连接到其依赖组件。 AMD模块系统提供了使用JavaScript模块来构建Web应用的完美方式,并且这种方式具有形式简单,异步加载和广泛采用的特点。

异步模块定义(AMD)格式是一套API,它用于定义可重用的并能在多种框架使用的模块。开发AMD是为了提供一种定义模块的方式,这种方式可以使用原生的浏览器脚本元素机制来实现模块的异步加载。AMD API由2009年Dojo 社区的讨论中产生,然后移动到讨论CommonJS如何更好的为浏览器适应CommonJS模块格式(被NodeJS使用)。 CommonJS已经发展成为单独的一个标准并有其专门的社区。AMD已经广泛普及,形成了众多模块加载实现并被广泛使用。在SitePen公司,我们广泛的使用Dojo的AMD机制工作,为其提供支持,并积极的建设这一机制。

本文中用到的一些重要词汇模块(module) —— 一个经过封装的JavaScript文件,它遵循模块的格式,指定依赖和提供模块输出。模块标识(module ID)——唯一标识模块的字符串,相对模块标识将根据当前模块的标识解释为绝对模块标识模块路径 (module path)——用于检索模块的URL。一个模块标识对应于一个模块路径,该路径是由加载器配置规则设定的(缺省情况下,模块路径假定为该模块对于根路径的相对路径,根路径通常是模块加载器包所在的父目录)。模块加载器(module loader)——解析和加载模块以及相关依赖的JavaScript代码,它与插件交互,并处理加载配置。包(package)——一组模块集合。例如dojo,dijit以及dgrid都是包。构建器(builder)——用于将模块(或者多个模块)以及其依赖连接在一起产生单个JavaScript文件的工具,这样使得一个应用程序能够包含多个模块,并能创建多个构建层次,从而使得它们在被加载时实现HTTP请求数目最小化。层(layer)——一个文件,它包含若干模块并由构建器优化生成单个文件。依赖(dependency)——为了使另一个模块正常工作而必须加载的模块。AMD——异步模块定义,一种为浏览器开发提供最优体验的模块定义格式。工厂方法(factory)——通过define定义的并提供给模块加载器的函数,它在所有依赖加载完后执行一次。为什么需要AMD模块?

模块化系统的基础前提是:

允许创建被封装的代码片段,也就是所谓的模块定义本模块与其他模块之间的依赖定义可以被其他模块使用的输出的功能谨慎的使用这些模块提供的功能AMD满足以上需求,并将依赖模块设置为其回调函数的参数从而实现在模块代码被执行前异步的加载这些依赖模块。AMD还提供了加载非AMD资源的插件系统。虽然有其他的load JavaScript的替代方法,但使用脚本元素来加载JavaScript有特有的优势,包括性能,减少调试(尤其在一些老版本的浏览器上)以及跨域的支持。因此AMD致力于提供基于浏览器开发的最优体验。

AMD格式提供了几个关键的好处。首先,它提供了一种紧凑的声明依赖的方式。通过简单的字符串数组来定义模块依赖,使得开发者能够花很小的代价轻松列举大量模块依赖性。

AMD帮助消除对全局变量的需求。 每个模块都通过局部变量引用或者返回对象来定义其依赖模块以及输出功能。因此,模块不需要引入全局变量就能够定义其功能并实现与其他模块的交互。AMD同时是“匿名的”,意味着模块不需要硬编码指向其路径的引用, 模块名仅依赖其文件名和目录路径,极大的降低了重构的工作量。

通过将依赖性映射为局部变量, AMD鼓励高效能的编码实践。如果没有AMD模块加载器,传统的JavaScript代码必须依赖层层嵌套的对象来“命名”给定的脚本或者模块。如果使用这种方式,通常需要通过一组属性来访问某个功能,这会造成全局变量的查找和众多属性的查找,增加了额外的开发工作同时降低了程序的性能。通过将模块依赖性映射为局部变量,只需要一个简单的局部变量就能访问某个功能,这是极其快速的并且能够被JavaScript引擎优化。

使用AMD

最基础的AMD API是define()方法,用于定义一个模块及其依赖。通常我们这样来写一个模块:


上图展示了由require()调用引起的一连串的依赖加载。require()的调用开启加载第一个模块,接着根据需要加载各模块的依赖模块。那些不需要的模块(如上图中的模块d)则永远不会被加载或者执行。

require()函数还可用于配置模块路径查找以及其他选项,但这一般来说对各个模块加载器都有特定的实现。更多信息请参考各个加载器关于配置细节的文档。

插件和Dojo最优化

AMD还支持加载其它资源的插件。这一点对于加载非AMD依赖非常有价值,例如加载HTML片段和模板,CSS,国际化相关的特定资源等。插件机制让我们在依赖列表中引用这些非AMD资源。语法如下:


使用构建

AMD最终揭秘

(译者注:原文作者选用的实验截图可能是本地资源加载的情况,由于本地资源加载的随机性,在使用构建之后优势不明显。但实际在网络传输中,使用构建会大大减少加载时间。)

性能

就像前面提到的那样,使用脚本元素注入比其他的方法快是因为它更依赖于原生的浏览器脚本加载机制。我们基于dojo.js创建了一些模块的测试用例,脚本元素加载比使用XHR eval的方式快了大概60-90%。在Chrome中,如果有大量的小模块,每个模块加载的时间大概是5-6ms

,而XHR+eval方式平均每个模块加载时间则接近9-10ms。在Firefox中,同步XHR方式比异步方式更快,而在IE中异步XHR比同步的快,但脚本元素加载无疑是最快的一个。让我们感到意外的是IE9是最快的一个浏览器,不过这有可能是因为在Firefox和Chrome中debugger/inspector增加了一些额外的性能开销。

AMD最终揭秘

模块加载器

AMD API是开放的,现在已有有多个AMD模块加载器和构造器的实现。这里介绍几个重要的AMD加载器:

Dojo – 这是一个完全的包括插件和构造器的AMD加载器。这是我们通常用来实现Dojo工具包的加载器。
  • RequireJS – 这是AMD加载器的元老也是AMD加载器的典范。其作者James Burke是AMD的主要作者和倡导者。这也是一个完整的包含构造器的加载器。
  • curl.js – 这是一个快速的AMD加载器,具有超级棒的插件支持(以及它自带的插件库)和自带的构造器。
  • lsjs – 这是一个专门设计用于在本地存储缓存模块的AMD模块加载器。其作者同时还写了一个独立的优化器。
  • NeedJS – 一个轻量级的AMD模块加载器。
  • brequire – 另一个轻量级的AMD模块加载器。
  • inject – 它是由LinkedIn创建并使用的,是一个快速轻量级的加载器,不提供对插件的支持。
  • Almond – 这是RequireJS的轻量级版本。获取AMD模块现在可以找到越来越多的AMD格式的包和模块。Dojo 基础包网站集中的给出了一个可以找到的包的列表。CPM 安装器 可以用于安装任何通过Dojo基础包网站注册的包(同时自动安装他们的依赖)。AMD最终揭秘

    James Burke, RequireJS的作者创建了 Volo——一个支持直接从github上面安装包的安装器。当然你也可以直接从他们的项目网站(在github或者其他地方)上直接下载模块,然后自己组织你的目录结构。有了AMD,我们就能够轻松的使用任何包而不仅仅是Dojo模块来构造应用程序。将普通的脚本转换成AMD也是非常简单的。你只需要在define中用一个空数组表面依赖,然后将脚本直接包含在define的回调函数体中。当然如果该脚本必须在其他某些脚本之后执行,你也可以添加依赖。例如:
    import {query} from "dojo/query.js";import {on} from "dojo/on.js";export function flashHeaderOnClick(button){    on(button, "click", function(){       query(".header").style("color", "red");    });}
    现在提出的新模块系统包括支持定制的模块加载器,它能够与新的模块系统交互,还能够用于保留某些AMD现存的某些特性,例如用插件访问非JavaScript资源。
    结论AMD为基于浏览器的网络应用提供了强大的模块化系统,它利于原生的浏览器加载方式实现异步加载,支持对各种形式的资源灵活访问的插件,同时用一个简单明了的格式来实现它的功能。由于有了类似Dojo,RequireJS等众多出色的AMD项目,AMD世界是让人兴奋的,并且为发展快速,可操作的JavaScript模块带来栩栩生机。.

    3楼QSCJOB13小时前
    [quote=okgoood]来错地方了!我还以为是CPU揭秘呢。[/quote]n同是这么以为的。
    2楼blackfireh昨天 10:24
    硬件需要和软件统一,amd做的很不错
    1楼okgoood昨天 09:01
    来错地方了!我还以为是CPU揭秘呢。

  • 热点排行