久闻r.js的大名,但实际没有用它做过任何东西。今天用它时,发现网上许多教程都不对。研究一下,把我的实际经验分享给大家。
例子1
先是HTML页面
<!DOCTYPE html> <html> <head> <title>My App</title> <link rel="stylesheet" type="text/css" href="css/main.css"> <script data-main="scripts/main-built" src="scripts/require.js"></script> </head> <body> <h1>My App</h1> </body> </html>
js都放在scripts目录下,换言之 html与scripts是平级。此目录下有r.js, require.js, one.js, two.js, three.js, main.js
上面HTML提到的main-built.js是一会儿动态生成的。
r.js 可以在这里找到https://github.com/jrburke/r.js/blob/master/dist/r.js,总共7MB,非常疯狂!听说把各种情况都hold住了, 比spm强大多了!
接着是几个JS的内容:
one.js
define(function(){ return 1 })
two.js
define(function(){ return 2 })
three.js
define(function(){ return 3 })
main.js
require(["one", "two", "three"], function (one, two, three) { alert(one+two+three) });
好了,我们再看一下build.js如何写
({ baseUrl: ".", name: "main", out: "main-built.js" })
定位到此目的,执行node r.js -o build.js
最后生成main-built.js文件,我格式化它一下,里面内容如下:
define("one",[],function(){return 1}), define("two",[],function(){return 2}), define("three",[],function(){return 3}), require(["one","two","three"],function(e,t,n){alert(e+t+n)}),define("main",function(){});
最后运行服务器,发现真的能alert出6!
例子2
就是在上面的例子里面改一下
其他变化如下:
three.js放到sub目录下,内容改成:
define(["./two"], function(a){ return 1 + a })
one.js
define(["./two"], function(a){ return 1 + a })
main.js改成
require(["one","sub/three"], function (one, three) { console.log(one + three) })
执行r.js,生成main-built.js为:
define("two", [], function() { return 2 }), define("one", ["./two"], function(e) { return 1 + e }), define("sub/three", [], function() { return 30 }), require(["one", "sub/three"], function(e, t) { console.log(e + t) }), define("main", function() { });
下面合并前后的请求数比较
例子3, paths配置项的使用
目录结构改成这样,jquery自行到官网下载
main.js改成这样
require.config({ paths: { jquery: "jquery/jquery-1.11.2" } }) require(["one", "sub/three","jquery"], function(one, three, $) { console.log(one + three) console.log($) });
main.js改成这样
({ baseUrl: ".", name: "main", paths: { jquery: "jquery/jquery-1.11.2" }, out: "main-built.js" })
然后执行node r.js -o build.js打包命令,生成的文件就可以用了。并且发现r.js有个非常智能的地方,如果把main.js中的require语句的依赖项中的jquery去掉,再执行打包,它会将jquery源码从main-built.js中去掉。
例子4, 让生产环境用的脚本放在另一个文件中
我们通常把我们自己工作的环境叫做发展环境, 上线的环境叫生产坏境,将它们分开是非常有好处的。我们把上面的目录复制一下,改一名字:
相对而言, 页面也改一下
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>My App</title> <link rel="stylesheet" type="text/css" href="css/main.css"> <script data-main="develop/main-built" src="develop/avalon.js"></script> <!-- <script data-main="develop/main" src="develop/avalon.js"></script>--> <!-- <script data-main="develop/main-built" src="develop/require.js"></script>--> </head> <body> <h1>My App</h1> </body> </html>
打包的脚本build.js变成这样,
({ baseUrl: ".", paths: { jquery: "jquery/jquery-1.11.2" }, dir: "../production", name: "main" })
对比一下,有了dir,就不能使用out配置项了,你在编译时它有非常明确的提示。执行node r.js -o build.js打包命令,你的项目变成这样了
既然目录变了,我们有两个办法,1自己修改或通过脚本修改index.html引用脚本的路径,2后端配置一下,对请求进行重定向,我们通常是使用后面一种。
例子5, shim配置项的使用
在例子4里面jquery目录添加一个jquery.aaa.js,内容如下:
jQuery.fn.aaa = function(){ alert("aaa") }
main.js改成
require.config({ paths: { jquery: "jquery/jquery-1.11.2", aaa: "jquery/jquery.aaa" }, shim: { aaa: { deps: ["jquery"], exports: "jQuery" } } }) require(["one", "sub/three", "aaa"], function(one, three, $) { console.log(one + three) console.log($.fn.aaa) })
build.js也跟着改成
require.config({ paths: { jquery: "jquery/jquery-1.11.2", aaa: "jquery/jquery.aaa" }, shim: { aaa: { deps: ["jquery"], exports: "jQuery" } } }) require(["one", "sub/three", "aaa"], function(one, three, $) { console.log(one + three) console.log($.fn.aaa) })
然后执行node r.js -o build.js打包命令,生成的文件就可以用了。
如果大家还有更好的打包方式, 可以https://github.com/avalonjs/avalonjs.github.io/tree/master/zh/engineering ,添加到这里,pull request给我