Gruntfile由如下几部分构成:html
每个 Gruntfile (和grunt插件)都遵循一样的格式,编写的Grunt代码都必须放在此包装函数内:至关因而gruntfile的入口;node
module.exports = function(grunt) { // Do grunt-related things in here };
大部分的Grunt任务(task)都依赖某些配置数据,这些数据被封装在一个object配置对象内,并做为参数传入grunt.initConfig 方法。git
grunt.initConfig({ Configuration data })
object配置对象首先 须要将存储在package.json
文件中的grunt 版本信息和各个插件的数据信息引入到grunt config中,即在配置对象中 加入下列语句:github
pkg:grunt.file.readJSON('package.json')
将package.json中的数据信息引入后,就能够编写任务配置了。下面以一个任务配置说明。npm
grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), //数据信息引入 uglify: { //插件任务属性配置 build: { //创建任务目标 src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } });
上述代码新建了一个以“uglify”为属性名的
grunt-contrib-uglify任务, 在任务中创建一个名为"build"
的uglify任务目标,用于将一个pkg.name.js文件压缩为一个目标文件pkg.name.min.js。因为<% %>
模板字符串能够引用任意的配置属性,所以能够经过这种方式来指定诸如文件路径和文件列表类型的配置数据,从而减小一些重复的工做。能够在这个配置对象中(传递给initConfig()方法的对象)存储任意的数据,只要它不与任务配置所需的属性相冲突就行,不然会被忽略。此外,因为这自己就是JavaScript,不只限于使用JSON;还能够在这里使用任意的有效的JS代码。若是有必要,甚至能够以编程的方式生成配置。编程
下面是grunt任务配置的具体说明:json
2.1 - Grunt任务配置具体说明api
Grunt的task配置都写在grunt.initConfig方法的配置对象中。任务配置主要是以 "任务名称" 命名的“属性”,这些属性名称是"固定"的,好比grunt-contrib-uglify对应的任务名称是” uglify”,固然也能够包含其余任意数据。可是这些表明任意数据的属性与任务所须要的属性相冲突时,这些任意数据的属性就会被覆盖。如如下的” concat”和” uglify”都是”任务名称” 属性数组
grunt.initConfig({ concat: { // 这里是concat任务的配置信息。 }, uglify: {// 这里是uglify任务的配置信息 }, my_property: 'whatever', // 任意数据。 my_src_files: ['foo/*.js', 'bar/*.js'], });
2.1.1 - options属性app
在一个任务配置中,options属性能够用来指定覆盖内置属性的默认值。此外,每个目标(target)中还能够拥有一个专门针对此目标(target)的options属性。目标(target)级的options将会覆盖任务级的options。 options对象是可选的,若是不须要,能够忽略。
grunt.initConfig({ concat: { options: { // 这里是任务级的Options,覆盖默认值 }, foo: { // 这里是目标级的Options,覆盖任务级的Options options: { //"foo" target options may go here, overriding task-level options. }, }, bar: { //No options specified; this target will use task-level options. },
}, });
2.1.2 - 任务的多目标配置
当运行一个任务时,Grunt会自动去查找配置对象中的同名任务名称属性。多任务(multi-task)能够经过任意命名的“目标(target)”来定义多个目标配置。以下所示concat任务有名为foo和bar两个目标,而uglify任务只有一个名为bar目标。
grunt.initConfig({ concat: { foo: {// concat task "foo" target options and files go here. }, bar: {// concat task "bar" target options and files go here. }, }, uglify: { bar: { // uglify task "bar" target options and files go here. }, }, });
同时指定任务(task)和目标(target),如grunt concat:foo或者grunt concat:bar,将只会处理指定目标(target)的配置,而运行grunt concat将遍历全部目标(target)并依次处理。注意,若是一个任务使用grunt.task.renameTask重命名过,Grunt将在配置对象中查找以新的任务名命名的属性。
2.2 - 文件
因为大多的任务都是对文件进行操做,Grunt有一个强大的抽象层用于声明任务应该操做哪些文件(即指明可操做文件)。下面有好几种定义src-dest(源文件-目标文件)文件映射的方式,均提供了不一样程度的描述和控制操做方式。任何一种多任务(multi-task)模式都能理解这些格式,因此只须要选择知足需求的格式就行。全部的文件格式都支持src和dest属性,此外"Compact"[简洁]和"Files Array"[文件数组]格式还支持如下一些额外的属性:
2.2.1 - 简洁格式
这种形式容许每一个目标对应一个src-dest文件映射。一般状况下它用于只读任务,好比grunt-contrib-jshint,它就只须要一个单一的src属性,而不须要关联的dest选项. 这种格式还支给每一个src-dest文件映射指定额外的属性。
grunt.initConfig({ jshint: { foo: { src: ['src/aa.js', 'src/aaa.js'] }, }, concat: { bar: { src: ['src/bb.js', 'src/bbb.js'], dest: 'dest/b.js', }, }, });
2.2.2 - 文件对象格式
这种形式支持每一个目标对应多个src-dest形式的文件映射,属性名就是目标文件,源文件就是它的值(源文件列表则使用数组格式声明)。可使用这种方式指定数个src-dest文件映射, 可是不可以给每一个映射指定附加的属性。
grunt.initConfig({ concat: { foo: { files: { 'dest/a.js': ['src/aa.js', 'src/aaa.js'], 'dest/a1.js': ['src/aa1.js', 'src/aaa1.js'], }, }, bar: { files: { 'dest/b.js': ['src/bb.js', 'src/bbb.js'], 'dest/b1.js': ['src/bb1.js', 'src/bbb1.js'], }, }, }, });
2.2.3 - 文件数组格式
这种形式支持每一个目标对应多个src-dest文件映射,同时也容许每一个映射拥有额外属性:
grunt.initConfig({ concat: { foo: { files: [ {src: ['src/aa.js', 'src/aaa.js'], dest: 'dest/a.js'}, {src: ['src/aa1.js', 'src/aaa1.js'], dest: 'dest/a1.js'}, ], }, bar: { files: [ {src: ['src/bb.js', 'src/bbb.js'], dest: 'dest/b/', nonull: true}, {src: ['src/bb1.js', 'src/bbb1.js'], dest: 'dest/b1/', filter: 'isFile'}, ], }, }, });
2.2.4 - 较老的格式
dest-as-target文件格式在多任务和目标出现以前是一个过渡形式,目标文件路径实际上就是目标名称。遗憾的是, 因为目标名称是文件路径,那么运行grunt task:target可能不合适。此外,你也不能指定一个目标级的options或者给每一个src-dest文件映射指定额外属性。此种格式已经不同意使用,请尽可能不要使用。
grunt.initConfig({ concat: { 'dest/a.js': ['src/aa.js', 'src/aaa.js'], 'dest/b.js': ['src/bb.js', 'src/bbb.js'], }, });
2.2.5 - 自定义过滤函数
filter属性能够给你的目标文件提供一个更高级的详细帮助信息。只须要使用一个有效的fs.Stats 方法名。下面的配置仅仅清理一个与模式匹配的真实的文件:
grunt.initConfig({ clean: { foo: { src: ['tmp/**/*'], filter: 'isFile', }, }, });
或者建立你本身的filter函数,根据文件是否匹配来返回true或者false。下面的例子将仅仅清理一个空目录: grunt.initConfig({ clean: { foo: { src: ['tmp/**/*'], filter: function(filepath) { return (grunt.file.isDir(filepath) && require('fs').readdirSync(filepath).length === 0); }, }, }, });
2.2.6 - 通配符模式
一般分别指定全部源文件路径是不切实际的,所以Grunt经过内置支持node-glob 和 minimatch 库来匹配文件名(又叫做globbing)。通常只须要知道如何在文件路径匹配过程当中使用它们便可:
foo/*.js将匹配位于foo/目录下的全部的.js结尾的文件;而foo/**/*js将匹配foo/目录以及其子目录中全部以.js结尾的文件。此外, 为了简化本来复杂的通配符模式,Grunt容许指定一个数组形式的文件路径或者一个通配符模式。全部模式按顺序处理,模式处理的过程当中,带有!前缀的模式所匹配的文件将不包含在结果集中。 并且其结果集中的每一项也是惟一的。
如:
// 指定单个文件: {src: 'foo/this.js', dest: ...} // 指定一个文件数组: {src: ['foo/this.js', 'foo/that.js', 'foo/the-other.js'], dest: ...} // 使用一个匹配模式: {src: 'foo/th*.js', dest: ...} // 一个独立的node-glob模式: {src: 'foo/{a,b}*.js', dest: ...} // 也能够这样编写: {src: ['foo/a*.js', 'foo/b*.js'], dest: ...} // foo目录中全部的.js文件,按字母顺序排序: {src: ['foo/*.js'], dest: ...} // 首先是bar.js,接着是剩下的.js文件,并按字母顺序排序: {src: ['foo/bar.js', 'foo/*.js'], dest: ...} // 除bar.js以外的全部的.js文件,按字母顺序排序: {src: ['foo/*.js', '!foo/bar.js'], dest: ...} // 按字母顺序排序的全部.js文件,可是bar.js在最后。 {src: ['foo/*.js', '!foo/bar.js', 'foo/bar.js'], dest: ...} // 模板也能够用于文件路径或者匹配模式中: {src: ['src/<%= basename %>.js'], dest: 'build/<%= basename %>.min.js'} // 它们也能够引用在配置中定义的其余文件列表: {src: ['foo/*.js', '<%= jshint.all.src %>'], dest: ...}
更多关于通配符模式的语法,请查看node-glob 和 minimatch 的文档。
2.2.7 - 动态构建文件对象 (经常使用)
当但愿处理大量的单个文件时,这里有一些附加的属性能够用来动态的构建一个文件列表。这些属性均可以用于Compact和Files Array文件映射格式。
expand 设置为true用于启用下面的选项:
在下面的例子中,uglify 任务中的static_mappings和dynamic_mappings两个目标具备相同的src-dest文件映射列表, 由于任务运行时Grunt会自动展开dynamic_mappings文件对象为4个单独的静态src-dest文件映射--假设这4个文件可以找到。
能够指定任意静态src-dest和动态的src-dest文件映射相互结合。
grunt.initConfig({ uglify: { static_mappings: { // Because these src-dest file mappings are manually specified, every // time a new file is added or removed, the Gruntfile has to be updated. files: [ {src: 'lib/a.js', dest: 'build/a.min.js'}, //静态src-dest,即文件路径和生成的文件路径是一对一的匹配 {src: 'lib/b.js', dest: 'build/b.min.js'}, {src: 'lib/subdir/c.js', dest: 'build/subdir/c.min.js'}, {src: 'lib/subdir/d.js', dest: 'build/subdir/d.min.js'}, ], }, dynamic_mappings: { // Grunt will search for "**/*.js" under "lib/" when the "uglify" task // runs and build the appropriate src-dest file mappings then, so you // don't need to update the Gruntfile when files are added or removed. files: [ { //动态的src-dest,文件路径和生成的文件路径是动态连接生成 expand: true, // Enable dynamic expansion. cwd: 'lib/', // Src matches are relative to this path. src: ['**/*.js'], // Actual pattern(s) to match. dest: 'build/', // Destination path prefix. ext: '.min.js', // Dest filepaths will have this extension. extDot: 'first' // Extensions in filenames begin after the first dot }, ], }, }, }); //两种文件映射方式效果相同,可是 动态的src-dest 效果更好,不用一个个进行匹配。
2.2.8 - 模板
使用<% %>分隔符指定的模板会在任务从它们的配置中读取相应的数据时将自动扩展扫描。模板会被递归的展开,直到配置中再也不存在遗留的模板相关的信息(与模板匹配的)。整个配置对象决定了属性上下文(模板中的属性)。此外,在模板中使用grunt以及它的方法都是有效的,如: <%= grunt.template.today('yyyy-mm-dd') %>。
下面以concat任务配置为例,运行grunt concat:sample时将经过banner中的/* abcde */连同foo/*.js+bar/*.js+bar/*.js匹配的全部文件来生成一个名为build/abcde.js的文件。
grunt.initConfig({ concat: { sample: { options: { banner: '/* <%= baz %> */\n', // '/* abcde */\n' }, src: ['<%= qux %>', 'baz/*.js'], // [['foo/*.js', 'bar/*.js'], 'baz/*.js'] dest: 'build/<%= baz %>.js', // 'build/abcde.js' }, }, //用于任务配置模板的任意属性 foo: 'c', bar: 'b<%= foo %>d', // 'bcd' baz: 'a<%= bar %>e', // 'abcde' qux: ['foo/*.js', 'bar/*.js'], });
2.2.9 - 导入外部数据
在下面的Gruntfile中,项目的元数据是从package.json文件中导入到Grunt配置中的,而且grunt-contrib-uglify 插件中的 uglify 任务被配置用于压缩一个源文件以及使用该元数据动态的生成一个banner注释。Grunt有grunt.file.readJSON和grunt.file.readYAML两个方法分别用于引入JSON和YAML数据。
grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, dist: { src: 'src/<%= pkg.name %>.js', dest: 'dist/<%= pkg.name %>.min.js' } } });
像 concatenation、[minification]、grunt-contrib-uglify 和 linting这些经常使用的任务(task)都已经以grunt插件的形式被开发出来了。经过npm install
安装之后,在 package.json
文件内会自动在dependency(依赖)添加这些插件的版本和链接信息,而后就能够在Gruntfile
中经过grunt.loadNpmTasks()函数加载这些插件:
grunt.loadNpmTasks('grunt-contrib-uglify'); //加载可以提供"uglify"任务的插件。加载其余插件和此方法相同
注意: grunt --help
命令将列出全部可用的任务。
经过定义 default
任务,可让Grunt默认执行一个或多个任务。如如下代码,执行 grunt
命令时若是不指定具体任务的话,将会执行uglify
任务。这和执行grunt uglify
或者 grunt default
的效果同样。default
任务列表数组中能够指定任意数目的任务(能够带参数;如['uglify:my_target'],则指明在执行uglify任务时执行my_target目标,其余目标不予执行)。
grunt.registerTask('default', ['uglify']); // Default task(s).
若是Grunt插件中的任务(task)不能知足项目需求,则能够在Gruntfile
中自定义任务(task)。例如,如下的 Gruntfile
中自定义了一个default
任务,能够不须要任务配置:
module.exports = function(grunt) { // A very basic default task. grunt.registerTask('default', 'Log some stuff.', function() { grunt.log.write('Logging some stuff...').ok(); }); };
特定于项目的任务没必要在 Gruntfile
中定义。他们能够定义在外部.js
文件中,并经过grunt.loadTasks方法加载。