Gruntfile 实例
下面就针对 Gruntfile 案例做简单分析,也可以作为实例使用:
module.exports = function(grunt) { grunt.initCon({ jshint: { files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'], options: { globals: { jQuery: true } } }, watch: { files: ['<%= jshint.files %>'], tasks: ['jshint'] } }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.registerTask('default', ['jshint']); };
在是这个 Gruntfile 实例的完整,如果你按顺序阅读本文的话,可以跟随我们一步步分析这个中的每一部分。我们会用到以下5个 Grunt :
第一部分是"wrapper" ,它包含了整个Grunt配置信息。
module.exports = function(grunt) { }
个中,我们可以初始化 conuration 对象:
grunt.initCon({ });
接下来可以从package.json 读入项目配置信息,并存入pkg 内。这样就可以让我们访问到package.json中列出的了,如下:
pkg: grunt.file.readJSON('package.json')
到目前为止我们就可以看到如下配置:
module.exports = function(grunt) { grunt.initCon({ pkg: grunt.file.readJSON('package.json') }); };
现在我们就可以为我们的每个任务来定义相应的配置(逐个定义我们为项目定义的任务配置),然后每个任务的配置对象作为Grunt配置对象(即grunt.initCon({})所接受的配置对象)的,并且这个与任务名相同。因此"concat"任务就是我们的配置对象中的"concat"键()。下面便是我的"concat"任务的配置对象。
concat: { options: { // 定义用于插入合并之字符 separator: ';' }, dist: { // 将要被合并的 src: ['src/**/*.js'], // 合并后的JS的存放位置 dest: 'dist/<%= pkg.name %>.js' } }
注意我是如何引用JSON(也就是我们在配置对象顶部引入的)中的name的。这里我使用pkg.name来访问我们刚才引入并存储在pkg中的package.json信息,它会被解析为JavaScript对象。
Grunt的有简单的模板引擎用于配置对象(这里是指package.json中的配置对象)值,这里我让concat任务将所有存在于src/目录下以.js结尾的合并起来,然后存储在dist目录中,并以项目名来命名。
现在我们来配置uglify,它的作用是压缩(minify)JavaScript:
uglify: { options: { // 此处定义的banner注释将插入到的顶部 banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' }, dist: { files: { 'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>'] } } }
这里我们让uglify在dist/目录中创建了包含压缩结果的JavaScript。注意这里我使用了<%= concat.dist.dest>,因此uglify会压缩concat任务中的。
QUnit的设置非常简单。 你只需要给它提供用于测试运行的的位置,注意这里的QUnit是运行在HTML上的。
qunit: { files: ['test/**/*.html'] },
JSHint的配置也很简单:
jshint: { // define the files to lint files: ['gruntfile.js', 'src/**/*.js', 'test/**/*.js'], // conure JSHint (documented at http://www.jshint.com/docs/) options: { // more options here if you want to override JSHint defaults globals: { jQuery: true, console: true, module: true } } }
JSHint只需要数组(也就是你需要检测的数组), 然后是options对象(这个对象用于重写JSHint提供的认检测规则)。
你可以到中查看完整的文档。如果你乐于使用JSHint提供的认配置,那么在Gruntfile中就不需要重新定义它们了。
最后,我们来看看watch:
watch: { files: ['<%= jshint.files %>'], tasks: ['jshint', 'qunit'] }
你可以在命令行使用grunt watch来运行这个任务。当它检测到任何你所指定的(我使用了JSHint任务中需要检测的相同的)发生变化时,它就会按照你所指定的顺序执行指定的任务(我指定了jshint和qunit任务)。
最后, 我们还要加载所需要的Grunt。 它们应该已经全部通过npm安装好了。
grunt.loadNpmTasks(''); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-concat');
最后设置了一些task。最重要的是default任务:
// 在命令行上输入"grunt test",test task就会被执行。 grunt.registerTask('test', ['jshint', 'qunit']); // 只需在命令行上输入"grunt",就会执行default task grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);
下面便是最终完成的 Gruntfile :
module.exports = function(grunt) { grunt.initCon({ pkg: grunt.file.readJSON('package.json'), concat: { options: { separator: ';' }, dist: { src: ['src/**/*.js'], dest: 'dist/<%= pkg.name %>.js' } }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' }, dist: { files: { 'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>'] } } }, qunit: { files: ['test/**/*.html'] }, jshint: { files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'], options: { //这里是覆盖JSHint认配置的选项 globals: { jQuery: true, console: true, module: true, document: true } } }, watch: { files: ['<%= jshint.files %>'], tasks: ['jshint', 'qunit'] } }); grunt.loadNpmTasks(''); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.registerTask('test', ['jshint', 'qunit']); grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']); };
Gruntfile.js实例:grunt-contrib-cssmin模块
现在通过cssmin模块,演示如何编写Gruntfile.js。cssmin模块的作用是最小化CSS。
首先,在项目的根目录下安装该模块。
npm install grunt-contrib-cssmin --save-dev
然后,新建Gruntfile.js。
module.exports = function(grunt) { grunt.initCon({ cssmin: { minify: { expand: true, cwd: 'css/', src: ['*.css', '!*.min.css'], dest: 'css/', ext: '.min.css' }, combine: { files: { 'css/out.min.css': ['css/part1.min.css', 'css/part2.min.css'] } } } }); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.registerTask('default', ['cssmin:minify','cssmin:combine']); };
下面详细解释上面中的三个,下面个来看。
1、grunt.loadNpmTasks
grunt.loadNpmTasks载入模块。
grunt.loadNpmTasks('grunt-contrib-cssmin');
你需要使用几个模块,这里就要写几条grunt.loadNpmTasks语句,将各个模块一一加载。
如果加载模块很多,这部分会非常冗长。而且,还存在问题,就是凡是加载的模块,也同时出现在package.json中。如果使用npm命令卸载模块以后,模块会从package.json中消失,但是必须手动从Gruntfile.js中清除,这样很不方便,一旦忘记,还会出现运行。这里有办法,就是安装load-grunt-tasks模块,然后在Gruntfile.js中,用下面的语句替代所有的grunt.loadNpmTasks语句。
require('load-grunt-tasks')(grunt);
这条语句的作用是分析package.json,加载所找到的grunt模块。
2、grunt.initCon
grunt.initCon用于模块配置,它接受对象作为参数。该对象的成员与使用的同名模块一一对应。由于我们要配置的是cssmin模块,所以里面有cssmin成员()。
cssmin()指向对象,该对象又包含多个成员。除了一些系统设定的成员(比如options),其他的成员称为目标(target)。模块可以有多个目标(target),上面里面,cssmin模块共有两个目标,是“minify”,用于压缩css;另是“combine”,用于将多个css合并。
每个目标的具体设置,需要参考该模板的文档。就cssmin来讲,minify目标的参数具体含义如下:
expand:如果设为true,就表示下面名的占位符(即*号)都要扩展成具体的名。
cwd:需要处理的(input)所在的目录。
src:表示需要处理的。如果采用数组形式,数组的每一项就是名,可以使用符。
dest:表示处理后的名或所在目录。
ext:表示处理后的后缀名。
除了上面这些参数,还有一些参数也是grunt所有模块通用的。
filter:返回布尔值的,用于过滤名。只有返回值为true的,才会被grunt处理。
dot:是否匹配以点号(.)开头的系统。
makeBase:如果设置为true,就只匹配路径的最后一部分。比如,a?b可以匹配/xyz/123/acb,而不匹配/xyz/acb/123。
关于符,含义如下:
*:匹配任意的字符,不/。
?:匹配单个字符,不/。
**:匹配任意的字符,/。
{}:允许使用逗号分隔的列表,表示“or”(或)关系。
!:用于模式的开头,表示只返回不匹配的情况。
比如,foo/*.js匹配foo目录下面的名以.js结尾的,foo/**/*.js匹配foo目录和它的所有子目录下面的名以.js结尾的,!*.css表示匹配所有后缀名不为“.css”的。
使用符设置src的更多例子:
{src: 'foo/th*.js'} {src: 'foo/{a,b}*.js'} {src: ['foo/a*.js', 'foo/b*.js']}
至于combine目标,就只有files参数,表示是css子目录下的out.min.css,输入则是css子目录下的part1.min.css和part2.min.css。
files参数的格式可以是对象,也可以是数组。
files: { 'dest/b.js': ['src/bb.js', 'src/bbb.js'], 'dest/b1.js': ['src/bb1.js', 'src/bbb1.js'], }, // or files: [ {src: ['src/aa.js', 'src/aaa.js'], dest: 'dest/a.js'}, {src: ['src/aa1.js', 'src/aaa1.js'], dest: 'dest/a1.js'}, ],
如果minify目标和combine目标的设置有重合的部分,可以另行定义与minify和combine平行的options。
grunt.initCon({ cssmin: { options: { /* ... */ }, minify: { /* ... */ }, combine: { /* ... */ } } });
3、grunt.registerTask
grunt.registerTask定义如何具体的任务。“default”任务表示如果不提供参数,直接输入grunt命令,则先运行“cssmin:minify”,后运行“cssmin:combine”,即先压缩再合并。如果只执行压缩,或者只执行合并,则需要在grunt命令后面指明“模块名:目标名”。
grunt # 认情况下,先压缩后合并 grunt cssmin:minify # 只压缩不合并 grunt css:combine # 只合并不压缩
如果不指明目标,只是指明模块,就表示将所有目标依次运行一遍。
grunt cssmin