本文主要讲如何使用Grunt实现RequireJS文件压缩。
一 说明
ES6出来前,RequireJS是JavaScript模块化最常用的方式之一。对于使用RequireJS构建的项目,要实现打包压缩,需要使用grunt-contrib-requirejs插件。
二 安装
npm install grunt-contrib-requirejs --save-dev
三 加载任务
grunt.loadNpmTasks('grunt-contrib-requirejs');
四 配置
在Gruntfile.js的配置对象中添加requirejs属性,该属性下可以配置多个目标任务对象,每个目标任务对象包含一个options对象。
注意:这个options的属性很多和requireJS的requirejs-config.js配置类似,但要注意这块配置是用于Grunt打包的,requirejs-config.js是用于非压缩模式下加载requireJS项目的。同一个项目中,这两个的配置一般情况基本一致,但有时也会有差别。但无论是那个,都要确保各个模块中依赖的模块地址都能找到,即baseUrl、paths、shim等配置必须确保所有模块中依赖的模块地址正确。
options对象有如下属性:
1)appDir
此处是文件Gruntfile的相对位置。
2) baseUrl
baseUrl 为加载文件的默认路径,不写默认路径用grunt打包的时候很容易报错找不到文件。
该路径相对于appDir,代表要查找js文件的起始文件夹,下文所有文件路径的定义都是基于这个baseUrl的。
例如1:设置为 ./src 是相对于index.html的。
例如2:如果appDir设置为‘./app’,baseUrl设置为‘src’,则实际默认路径是‘./app/src’。
3) name
要打包的js入口文件地址和名字。
注意:该地址是相对于baseUrl的。
4) optimize
是否进行混淆优化,可选值:‘uglify’、‘none’。默认值是none。
5) paths
该属性和RequireJs的配置路径项类似,就是对requireJS模块中依赖的地址进行配置。
"paths" : { 'cModule' : 'src/c', 'jquery' : 'lib/jquery' },
6) shim
该属性和RequireJS的配置项一样,都是为没有使用RequireJS的define()方法声明依赖关系的第三库,来声明各个第三方库的依赖和对外的全局变量。
shim是一个对象, Key 值(cate) 与上边paths中定义的名字一样.每个属性对象有deps和exports两个属性,分别定义该库的依赖和对外全局变量。
例如:AngularJS依赖jquery,AngularJS对外的全局变量是angular;jquery对外的全局变量是$.
1 "paths" : { 2 'cModule' : 'src/c', 3 'jquery' : 'lib/jquery', 4 'angular' : 'lib/angular' 5 }, 6 "shim" : { // shim 中定义一个JSON对象, Key 值(cate) 与paths中定义的名字一样 7 'jquery' : { // shim中的JSON对象有两个属性: deps,exports 8 'deps' : [], // deps 为数组,表示其依赖的库 9 'exports' : '$' // exports 表示输出的对象名(标志该第三方库的全局变量标志) 10 }, 11 'angular' : { 12 'deps' : ['jquery'], 13 'export' : 'angular' 14 } 15 }
7) out
设置压缩后的文件地址和文件名。
例如:‘dist/test.min.js’。
8)removeCombined
如果为true,将从输出目录中删除已合并的文件。注意:该配置只有在设置了dir情况下生效。
9)dir
保存输出的路径,如果只输出一个文件,可以使用out接口。如果输出多个文件,都会放在dir下。
五 实战
下边是一个实例项目。
5.1 整体项目目录如下:
5.2 Gruntfile.js配置如下:
1 module.exports = function (grunt) { 2 grunt.initConfig({ 3 // 清理空文件夹 4 clean: { 5 foo1: { 6 src: ['dist/*'] 7 } 8 }, 9 requirejs: { 10 min: { 11 options: { 12 baseUrl: './', 13 optimize: 'none', 14 name: 'build', 15 out: 'dist/test.min.js', 16 // dir: 'dist', 17 removeCombined: true, 18 paths: { 19 cModule: 'src/c', 20 jquery: 'lib/jquery', 21 angular: 'lib/angular' 22 }, 23 shim: { 24 jquery: { 25 deps: [], 26 exports: '$' 27 }, 28 angular: { 29 deps: ['jquery'], 30 exports: 'angular' 31 } 32 }, 33 34 } 35 } 36 }, 37 38 }); 39 40 grunt.loadNpmTasks('grunt-contrib-requirejs'); 41 grunt.loadNpmTasks('grunt-contrib-clean'); 42 43 // 默认被执行的任务列表。 44 grunt.registerTask('default', [ 45 'clean', 46 'requirejs' 47 ]); 48 49 };
5.3 入口文件build.js代码如下:
说明:入口文件必须是一个require()方法模块,而不能是一个define定义模块。不然会报错。
1 require([ 2 'src/b' 3 ]);
5.4 入口文件中加载的b.js文件代码如下:
1 define(['src/a', 'cModule/c', 'src/jq/jq', 'src/ng/ng'], function (a, c, jq, ng) { 2 window.console.log(a.name); 3 window.console.log(c); 4 window.console.log(jq); 5 window.console.log(ng); 6 7 var b = 'this is a log!' 8 return b; 9 });
5.5 其它各个文件说明:
jq.js文件用于引入jquery库;
ng.js文件用于引入AngularJS库;
其它各个文件都是简单的RequireJS模块文件。
六 实战示例源码
上边实战示例源码获取地址:
https://gitee.com/bangbangwa/grunt/blob/master/grunt-contrib-requirejs-test.rar
参考资料&内容来源:
Grunt官网:https://www.npmjs.com/package/grunt-contrib-requirejs
编程网志:http://www.codeweblog.com/requirejs-angularjs-grunt-contrib-requirejs-%E7%BA%AF%E6%89%8B%E6%95%B2-%E5%B9%B2%E8%B4%A7/
reuqireJS官网:http://www.requirejs.cn/