这一章节大量基于优秀的RequireJS文档http://requirejs.org/docs/jquery.html,并且得到RequireJS作者James Burke的许可。
当项目达到一定规模时,管理项目的脚本模块开始变得非常棘手。你显然需要按正确的次序组织好这些脚本,并且开始认真考虑将脚本打包部署,只让一个或少数请求去载入这些脚本。你或许还想在页面加载完成后立即加载这些脚本代码。 When a project reaches a certain size, managing the script modules for a project starts to get tricky. You need to be sure to sequence the scripts in the right order, and you need to start seriously thinking about combining scripts together into a bundle for deployment, so that only one or a very small number of requests are made to load the scripts. You may also want to load code on the fly, after page load.
RequireJS是James Burke设计的一个依赖管理工具,它可以帮助你管理脚本模块并以正确的次序加载脚本,不需要改变标记即可以通过RequireJS优化工具轻松组合后续的脚本。它提供一种简单的方式在页面加载完成后载入脚本,随着时间的推移可以有效扩充脚本文件的尺寸。
RequireJS的模块系统可以帮助你定义作用域良好的模块,即使你却不关注这套系统也能获得依赖管理和构建时优化的好处。如果你开始创建模块化的代码并在少数场合重用它们,久而久之,RequireJS的模块格式会使编写联机加载的封装代码十分简单。特别是你想使用国际化字符串,让你的项目针对不同语言进行本地化,或者加载HTML字符串并确保在执行代码前这些字符串确实有效,或者只是把JSONP服务当作依赖关系来使用,RequireJS都是你的得力伙伴。
在jQuery中使用RequireJS最简单的方式是下载一个内建RequireJS的jQuery构建版本。这个构建版本不包括RequireJS和jQuery功能发生重复的部分。你还会发现下载使用RequireJS的jQuery示例项目对你也很有帮助。
在页面中使用RequireJS相当简单:只需要引入内建RequireJS的jQuery和你的应用程序文件。下面的示例假设jQuery和你的其它脚本都位于scripts/
目录。
Example 10.5. 使用RequireJS:一个简单示例
<!DOCTYPE html> <html> <head> <title>jQuery+RequireJS Sample Page</title> <script src="scripts/require-jquery.js"></script> <script>require(["app"]);</script> </head> <body> <h1>jQuery+RequireJS Sample Page</h1> </body> </html>
调用require(["app"])
是在告诉RequireJS加载scripts/app.js
文件。RequireJS将从require-jquery.js
所在的目录加载所有传入require()
的依赖脚本,且不需要.js
扩展名,不过也可以将它配置成另一种完全不同的工作方式。如果你乐意使用完整路径,还可以通过下面的方式来处理:
<script>require(["scripts/app.js"]);</script>
app.js
里有什么?有另一种方式可以调用require.js
来加载你需要的脚本,在页面中随心所欲的进行初始化工作。这个示例中app.js
脚本加载了两个插件:jquery.alpha.js
和jquery.beta.js
(不是什么真正的插件,只是随便举个例子)。这些插件需要放进和require-jquery.js
相同的目录:
Example 10.6. 使用依赖的简单JavaScript文件
require(["jquery.alpha", "jquery.beta"], function() { //jquery.alpha.js和jquery.beta.js插件已经加载。 $(function() { $('body').alpha().beta(); }); });
通过require.def()
,RequireJS让定义可重用的模块变得十分简单。RequireJS模块可以使用依赖来定义一个模块,并且Require模块可以返回一个值——不管是一个对象还是一个函数——并让其它模块来使用。
如果你的模块没有任何依赖性,只需要指定一个模块名称作为第一个参数调用require.def()
。第二个参数只是一个定义了模块属性的对象原语。例如:
Example 10.7. 定义一个没有依赖性的RequireJS模块
require.def("my/simpleshirt", { color: "black", size: "unisize" } );
这个示例将被放到my/simpleshirt.js文件中。
如果你的模块存在依赖性,你可以将依赖关系作为第二个参数传递给require.def()
(用数组的方式),接着传递一个函数作为第三个参数。这个函数将在所有依赖关系加载完成后被调用,以便定义这个模块。
Example 10.8. 定义一个有依赖性的RequireJS模块
require.def("my/shirt", ["my/cart", "my/inventory"], function(cart, inventory) { //返回一个对象以便定义"my/shirt"模块。 return { color: "blue", size: "large" addToCart: function() { inventory.decrement(this); cart.add(this); } } } );
在这个例子里创建了my/shirt模块,它依赖于my/cart和my/inventory。在磁盘上,这些文件被构造成这样:
my/cart.js my/inventory.js my/shirt.js
定义my/shirt
的函数在my/cart
和my/inventory
加载前不会被调用,函数以cart
和inventory
参数接收模块。函数参数的顺序必须和依赖关系数组中的依赖关系次序一致。调用函数后返回的对象定义了my/shirt
模块。通过这种方式定义模块,my/shirt
不会作为一个全局对象存在。在模块中定义全局变量被明确地阻止,所以同一时间可以在同一个页面使用多个不同版本的模块。
模块中返回对象不是必需的;允许从函数中返回任何有效值。
Example 10.9. 定义一个返回函数的RequireJS模块
require.def("my/title", ["my/dependency1", "my/dependency2"], function(dep1, dep2) { //返回一个函数以定义"my/title",该函数可返回或设置窗口标题。 return function(title) { return title ? (window.title = title) : window.title; } } );
每个JavaScript文件必须只有唯一的一个模块。
一旦你结合RequireJS进行依赖管理,实施页面优化将会非常简单。下载RequireJS源文件并放到你喜欢的任何地方,最好是放到web开发以外的区域。因为这个例子的原因,RequireJS源文件被放到了webapp
的同一级目录,它包括了HTML页面和包含所有脚本的目录。完整的目录结构如下:
requirejs/ (用于构建工具) webapp/app.html webapp/scripts/app.js webapp/scripts/require-jquery.js webapp/scripts/jquery.alpha.js webapp/scripts/jquery.beta.js
接着,在这个拥有require-jquery.js
和app.js的脚本目录里,创建叫作app.build.js的文件,并且具有下列内容:
Example 10.10. RequireJS构建配置文件
{ appDir: "../", baseUrl: "scripts/", dir: "../../webapp-build", //如果你想通过闭包编译器用"simple"优化模式压缩代码, //可以注释掉optimize这一行 optimize: "none", modules: [ { name: "app" } ] }
要使用这个构建工具,你需要安装Java 6。闭包编译器用于JavaScript压缩环节(如果optimize:
"none"
被注释掉),它需要Java 6的支持。
要开始进行构建工作,需进入webapp/scripts目录,执行下列命令:
# 非Windows系统 ../../requirejs/build/build.sh app.build.js # Windows系统 ..\..\requirejs\build\build.bat app.build.js
现在,webapp-build目录中将会生成app.js
,jquery.alpha.js
和jquery.beta.js
这样几个文件。如果在浏览器中打开webapp-build
目录中的app.html
文件,你不会看到任何加载jquery.alpha.js
和jquery.beta.js
的网络请求。
Copyright Rebecca Murphey, released under the Creative Commons Attribution-Share Alike 3.0 United States license.