前言
Javascript模块化编程系列一: 模块化的驱动
在前一篇介绍了为什么要进行Javascript模块化编程。至于如何实现模块化,不同的开发组织和个人具体的实现方式肯定是不一样。如何统一一个规范呢?
CommonJS 就在做的工作就包含了这部分。
CommonJS
CommonJS 是一个由服务的Javascript运行库作者组成的小组,他们一直致力于暴露及访问模块的标准化工作。值得注意的是,他们提议的模块系统不是来自于创建Javascript标准同一小组的一个标准,它更多地成为Javascript运行库作者之间的非正式约定。
CommonJS 只是定义一些标准和规范,不参与标准库的实现。
其官方对于自身的介绍是:
CommonJS API定义很多普通应用程序(主要指非浏览器的应用)使用的API,从而填补了这个空白。它的终极目标是提供一个类似Python,Ruby和Java标 准库。这样的话,开发者可以使用CommonJS API编写应用程序,然后这些应用可以运行在不同的JavaScript解释器和不同的主机环境中。在兼容CommonJS的系统中,你可以使用 JavaScript程序开发:
- 服务器端JavaScript应用程序
- 命令行工具
- 图形界面应用程序
- 混合应用程序(如,Titanium或Adobe AIR)
CommonJS的规范包括:
模块(modules)、包(packages)、系统(system)、二进制(binary)、控制台(console)、编码(encodings)、文件系统(filesystems)、套接字(sockets)、单元测试(unit testing)等
已经发布的标准有 Modules/1.0、Modules/1.1、Modules/1.1.1、Packages/1.0、System/1.0。
最新的发布规范和建议及开发中的标准可以到 http://www.commonjs.org/specs/
目前有实现CommonJS规范的项目比较多(遵循和实现部分规范),比较出名的有: Node.js , RequireJS;
更多的项目可以到 http://www.commonjs.org/impl/ 查看。
未来CommonJS还需要加入的底层API定义包括(语言和运行时环境、日志、关系数据库接口、结果集、并发、字符串/字节序列/IO、目标平台的C语言标准统一的API和子进程):
- Language and Runtime Services
- Logging
- Relational database interface
- ResultSets (collections of data maybe from RDBMS, maybe from other sources)
- Concurrency
- String / ByteString I/O
- C unified API to our Target Platforms
- Subprocesses (popen)
高层API包括(HTTP客户端API、Email、Jabber、国际化、Promise管理器、命令行处理):
- HTTP client APIs
- Email
- Jabber (XMPP)
- Internationalization
- Promise Manager
- Command line processing
这些都可以在CommonJS自己的Wiki上找到。
AMD
从以上CommonJS的介绍不难看出, Modules 的定义在CommonJS的初期和现在都是重点的内容, 那我们在使用dojo 开发时,看到的AMD 又是什么呢?
AMD(异步模块定义,Asynchronous Module Definition)格式总体的目标是为现在的开发者提供一个可用的模块化 JavaScript 的解决方案。它诞生于 Dojo 在使用 XHR+eval 时的实践经验,其支持者希望未来的解决方案都可以免受由于过去方案的缺陷所带来的麻烦。
AMD 模块格式本身是一个关于如何定义模块的提案,在这种定义下模块和依赖项都能够异步地进行加载。它有很多独特的优势,包括天生的异步及高度灵活等特性,这些特性能够解除常见的代码与模块标识间的那种紧密耦合。它被许多开发者所青睐,可以认为它是迈向 ES Harmony 中提出的模块系统的一块可靠基石。
AMD 最初是一份 CommonJS 列表中模块格式的规范草案,但因为没能达成完整的共识,格式的后续开发就被移到了 amdjs 讨论组中。
目前它已经被包括 Dojo (1.7)、MooTools (2.0)、Firebug (1.8) 甚至 jQuery (1.7) 这样的项目所接纳。尽管我们时不时还是会遇到 CommonJS AMD 格式 这个说法,但由于不是所有 CJS 列表上的参与者都愿意支持它,我们最好还是称它为 AMD 或是异步模块支持。
注:曾经有一段时间,这个提案还被称为 Modules Transport/C,但是这个规范并不适合用来传输现有的 CJS 模块,而是适合用来定义模块,所以选择 AMD 这个命名约定就显得更为合理了。
为什么 AMD 对于编写模块化 JavaScript 是一个更好的选择?
- 为如何定义高灵活性的模块提供了一个清晰的方案。
- 相对目前我们很多人使用的全局命名空间加注入
<script>
标签的解决方案来说,要简洁得多。它有一个简洁的方式来声明独立的模块以及他们可能包含的依赖项。
- 模块定义都被封装了起来,帮我们避免了全局命名空间的污染。
- 比其它替代方案(例如 CommonJS,我们马上会讨论到)效果更好。没有跨域、本地或调试带来的问题,也不依赖于服务器端工具。大多数 AMD 加载器都支持在浏览器中加载模块,而不须要一个构建的过程。
- 提供了一个“传输”方法来用在单个文件中包含多个模块。其它例如 CommonJS 这样的方式都尚没有对传输格式达成共识。
- 当需要时可以进行延迟加载。
AMD 目前的位置是 : https://github.com/amdjs/amdjs-api/wiki
参考
使用 AMD、CommonJS 及 ES Harmony 编写模块化的 JavaScript