如果你已经熟悉RequireJS的基本配置和使用,可以直接跳到30分钟上手RequireJS打包及优化 。
本机环境:
OS: Yosemite 10.10.2
Git: 1.9.5
Nodejs: 0.10.32
requirejs: 2.1.19
###为什么折腾RequireJS 在2015年8月份以前,我没有理解过什么是AMD,什么是CMD。我也从来没有想过有需要去了解。毕竟library这些东西,上手知道大概怎么用就好了。直到我因为想要调整工作项目框架中的Gruntfile。
它里面RequireJS配置的部分简直就是毒瘤 一样的存在,所以激发了我要折腾RequireJS明白的欲望。
作为一个循规蹈矩的人,想要了解一个工具,当然是从官网 开始了。
RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node. Using a modular script loader like RequireJS will improve the speed and quality of your code.
Yaaayyy!没有看明白!!!
加之所有需要细看的正文字体都好小,不想看怎么办……
看来只能召唤大谷歌了。
所以这篇将是大杂烩式的记录。
###文件夹结构 这次的初始文件夹结构如下,我事先把需要用到的JS文件都复制好了在assets/js/lib
下。
1
2
3
4
5
6
7
8
9
10
11
dev
├── assets
│ └── js
│ ├── lib
│ │ ├── backbone-1.1.2.min.js
│ │ ├── jquery-1.11.2.min.js
│ │ ├── requirejs-2.1.19.min.js
│ │ └── underscore-1.8.3.min.js
│ └── requirejsConfig.js
├── index-modern.html
└── index-old-school.html
###瘦身前后快照对比 老式的JS文件引入方法,就是在HTML底部一个一个script
地加,而且还一定要理好顺序,否则浏览器就要发你脾气。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html >
<head >
<meta charset ="UTF-8" >
<title > Old School Way</title >
</head >
<body >
<p class ="lineOne" > </p >
<p class ="lineTwo" > </p >
<p class ="lineThree" > </p >
</body >
<script src ="assets/js/lib/jquery-1.11.2.min.js" charset ="utf-8" > </script >
<script src ="assets/js/lib/underscore-1.8.3.min.js" charset ="utf-8" > </script >
<script src ="assets/js/lib/backbone-1.1.2.min.js" charset ="utf-8" > </script >
<script type ="text/javascript" >
(function ( ) {
$('.lineOne' ).text('This page is showing you the old school way of including js files' );
$('.lineTwo' ).text('-- including them one after another behind the <body> tag.' );
$('.lineThree' ).text('Check the HTML code!' );
})()
</script >
</html >
然后我们来感受一下RequireJS的苗条。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<html >
<head >
<meta charset ="UTF-8" >
<title > Modern Way</title >
</head >
<body >
<p class ="lineOne" > </p >
<p class ="lineTwo" > </p >
<p class ="lineThree" > </p >
</body >
<script data-main ="assets/js/requirejsConfig" src ="assets/js/lib/requirejs-2.1.19.min.js" > </script >
<script type ="text/javascript" >
(function ( ) {
$('.lineOne' ).text('This page is showing you the MODERN way of including js files' );
$('.lineTwo' ).text('-- using REQUIRE JS!!!.' );
$('.lineThree' ).text('Check the HTML code!' );
})()
</script >
</html >
看到这里,你一定会说,这不科学,单单引入RequireJS就可以?你是出来骗小学生的吧?想要达到根上面一样的效果,不引入要用的那些库,浏览器根本就是罢工好吗?
这就是即将要说明的:
data-main的魔法 RequireJS苗条版,除了只引入了RequireJS本身,最可疑的地方就是这个script
的data-main
属性了。assets/js/requirejsConfig
看上去是个文件路径吧?说!里面写了些什么?
既然你这么机灵,没办法,只能坦白从宽了。
data-main
指向的文件,其实可以看成是RequireJS的配置文件。加载完RequireJS以后,第一张会加载的script
就是data-main
所指。
requirejs.config 在assets/js/requirejsConfig
里面,使用requirejs.config方法对RequireJS进行配置。接下来会从简说明一下配置文件中常用的参数。
注意: requirejs.config中的文件路径均为相对于index.html的路径。
baseUrl
是本config文件中用到的所有文件的路径base。所有文件最终形式都是baseUrl + path(接下来马上会说明)。
以jquery为例,如下配置以后RequireJS就会知道,jquery的路径为:‘assets/js/lib/jquery-1.11.2.min.js’。
1
2
3
4
5
6
7
8
9
10
11
12
13
paths: {
jquery : 'lib/jquery-1.11.2.min' ,
underscore: 'lib/underscore-1.8.3.min' ,
backbone : 'lib/backbone-1.1.2.min' ,
requirejs : 'lib/requirejs-2.1.19.min'
backbone : [
'//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min' ,
'backbone-1.1.2.min'
]
}
Tips:一个个找文件路径很麻烦?如果你的项目中有使用Bower,用bower --paths
命令,就可以轻松列出所有包的路径了。
定义好paths以后,在使用define方法的时候,就可以直接使用paths对象里面的key,不需要写长到爆的JS文件名了。
define方法 在苗条版最下方,你会看到我还是用了老方法来执行jquery方法。下面我们一起来尝试RequireJS的define方法吧。
首先把苗条版最后的jquery方法提取出来,放到assets/js/tipText.js
里面:
1
2
3
4
5
define(['jquery' ], function ($ ) {
$('.lineOne' ).text('This page is showing you the MODERN way of including js files' );
$('.lineTwo' ).text('-- using REQUIRE JS!!!.' );
$('.lineThree' ).text('Check the HTML code!' );
});
define方法接受的参数,第一个是需要依赖的模块,以数组形式传入。在接下来的function中,记得一定要对应数组顺序 ,给它传入参数。
比方说,我的依赖模块是jquery和underscore,function的参数就需要按顺序是$
和_
。
1
define(['jquery' , 'underscore' ], function ($, _ ) { ...... });
如果你非要给function先传_
再$
,也不是不可以。只要你记得_
是jquery,$
是underscore就好了。
非要试一下是吧?没问题,直接尝试下面这样写,然后刷新页面。
1
2
3
define(['jquery' , 'underscore' ], function ($, _ ) {
$('.lineThree' ).text('Check the HTML code!' );
});
……
相信了吧?
乖乖地按照顺序 来吧。
但是如果要依赖的模块超级多,要一个一个写到数组里面然后在function里面对应加,那会烦到爆啊!
对!所以可以像下面这样写:
1
2
3
4
5
define(function (require ) {
var $ = require ('jquery' );
var _ = require ('underscore' );
......
});
require方法 好了,既然我们把原有的jquery方法提取了出来,接着要怎么使用呢?
很简单,为了方便我们暂时直接在引用完RequireJS之后调用require方法吧。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html >
<head >
<meta charset ="UTF-8" >
<title > Modern Way</title >
</head >
<body >
<p class ="lineOne" > </p >
<p class ="lineTwo" > </p >
<p class ="lineThree" > </p >
</body >
<script data-main ="assets/js/requirejsConfig" src ="assets/js/lib/requirejs-2.1.19.min.js" > </script >
<script type ="text/javascript" >
require (['tipText' ], function (tipText ) { });
</script >
</html >
由于我们的tipText文件目前只是对html做了一些简单处理,直接这样就可以了。刷新页面可以看到效果。
require方法接受的参数和参数规则与define方法一致。
1
require (['tipText' ], function (tipText ) { });
数组中依赖的模块,使用相对requirejsConfig.js
的路径。试一下在dev下面新建testRequire.js
文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
dev
├── assets
│ └── js
│ ├── lib
│ │ ├── backbone-1.1.2.min.js
│ │ ├── jquery-1.11.2.min.js
│ │ ├── requirejs-2.1.19.min.js
│ │ └── underscore-1.8.3.min.js
│ ├── requirejsConfig.js
│ └── tipText.js
├── index-modern.html
├── index-old-school.html
└── testRequire.js /* require方法引用模块路径测试文件 */
如果直接在require方法中这样引入,RequireJS是会报script error的。因为与requirejsConfig.js
同级的文件中找不到testRequire.js
。
1
require (['tipText' , 'testRequire' ], function (tipText, testRequire ) { });
改成下面这样页面就可以正常显示了。
1
require (['tipText' , '../../testRequire' ], function (tipText, testRequire ) { });
###普通js也可以作为模块引入吗? 答案是,让人兴奋的,可以 哟~
下面我们直接在js文件夹新建global.js
文件,文件里面就这样定义一个简单对象。
1
2
3
var GLOBALVAR = {
amd: 'requirejs'
};
在requireConfig.js
里面,增加一个参数:
1
2
3
4
5
6
7
shim: {
'global' : {
exports: 'GLOBALVAR'
}
}
在require方法中:
1
2
3
4
require (['tipText' , '../../testRequire' , 'global' ], function (tipText, testRequire, GLOBALVAR ) {
console .log(GLOBALVAR);
});
基本原理总结
引入RequireJS, 在data-main属性中指明配置文件
使用define方法自定义模块。define时声明需要依赖的模块
通过require方法使用自定义的模块。RequireJS会知道自定义模块依赖了哪些模块并一起加载
如果你已经熟悉RequireJS的基本配置和使用,可以直接跳到30分钟上手RequireJS打包及优化 。