本篇记录的是在不适用任何自动化工具(如GruntGulp)的情况下,使用r.js对项目进行打包和优化。
使用自动化工具时配置的方法基本大同小异,届时根据该工具所用插件的文档进行适当调整即可。

本机环境:

  • OS: Yosemite 10.10.2
  • Git: 1.9.5
  • Nodejs: 0.10.32
  • requirejs: 2.1.19

几个简单的优化目标:

  • 把通用库打包到一个文件
  • 自定义的模块按需进行合并
  • js文件压缩

文件夹结构

首先,我从官网链接找到r.js,并下载到对应文件夹中。

当前文件夹结构如下(文件夹中的内容均与30分钟上手RequireJS的一致):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
dev
├── assets
│   └── js
│   ├── comm on.js /* 此文件为空,是为了最后把通用依赖包都打包到一齐而准备的。*/
│   ├── global.js
│   ├── lib
│   │   ├── backbone-1.1.2.min.js
│   │   ├── jquery-1.11.2.min.js
│   │   ├── r.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

创建build.js

dev文件夹的同层新建build.js文件。它是使用r.js进行优化时需要用到的配置文件。

期望在进行优化后,文件夹结构如下:

1
2
3
4
.
├── dev
├── dist /* 最后使用r.js创建的文件夹,不需要手动创建 */
└── build.js

接下来看看build.js文件常用的配置项:

1
appDir: 'dev'

appDir顾名思义,指向的就是项目源文件的文件夹。

1
baseUrl: 'assets/js'

baseUrl指的是模块文件的base路径。

1
dir: 'dist'

dir指向的是优化后的文件的存放文件夹。

所以,appDir 是源,dir是目的地。

1
mainConfigFile: 'dev/assets/js/requirejsConfig.js',

mainConfigFile指向的是RequireJS的配置文件,详情可见30分钟上手RequireJS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
modules: [
/* 首先定义通用的module */
{
/* 每个module的name是相对于baseUrl的路径 */
name: 'common',
include: [
'jquery',
'backbone',
'underscore',
'requirejs'
]
},
/* 下面是每一个页面需要用到的模块 */
/* include页面依赖的模块,这里只把tipText和global合并 */
/* exclude已经打包好的common */
{
name: 'tipText',
include: ['tipText', 'global'],
exclude: ['common']
}
]

modules就是进行打包合并的重点部分。首先把通用的依赖包打包到common.js里面。再处理每一个页面需要的模块。由于已经有common这个模块,各个页面的模块中就不需要把它包含在内了。

1
2
3
paths: {
backbone: 'empty:'
}

requirejsConfig.js中设置了从CDN请求的文件,必须作如下设置,否则会报错。

1
optimize: 'uglify2'

optimize项配置的是需要使用的JS压缩引擎。

1
optimizeCss: 'standard'

optimizeCss顾名思义,压缩CSS的模式。配置standard就可以压缩CSS文件。
这时候,也许你会说,连CSS都可以帮忙压缩真是太强大了。而我个人就认为:未免管得太多了。

更多配置选项,可以参考官方的example.build.js

开始打包和优化

进入项目文件夹下,运行以下命令,就可以开始打包和优化了。

1
node dev/assets/js/lib/r.js -o build.js

完成以后打开build文件夹中的index-morden.html, 跟原来的一样,没有变化。

1
2
3
require(['tipText', 'global', '../../testRequire'], function (tipText, GLOBALVAR, test) {
console.log(GLOBALVAR);
});

但其实这个时候已经不需要分别require tipTextglobal了,因为已经合并到tipText文件中,所以可以改成:

1
2
3
require(['tipText', '../../testRequire'], function (tipText, test) {
console.log(GLOBALVAR);
});

打开控制台,刷新页面,依然可以见到log出来的GLOBALVAR对象。

在开发者工具的networks查看tipText.js,可以见到其实源代码中的tipTextglobal的内容已经合并,并且压缩。

主观使用感受

  1. 初学者极度不友好。无论是RequireJS本身,还是优化工具r.js,都需要各种繁琐的配置。
  2. 没有简明清晰的说明文档。文档是很详尽,可惜我没有看明白。花了很多时间去搜索研究,极大地增加了学习成本。
  3. 打包前后require的文件可能会变化。我把tipTextglobal合并了,还要到引用的地方改一下。(可能是还没有找到章法吧)
  4. 研究到了最后,并没有预期中的效果那么好。(预期:各种配置?好吧,好好配置,不然机器怎么知道哪是哪呢?结果:怎么我都配好了,还是有浓重的不智能感?)