配置任务
使用 Gruntfile
为项目配置任务。
Grunt 配置
任务配置定义在 Gruntfile
的 grunt.initConfig
方法中。配置主要是以任务命名的属性,也可以包含其他数据,但不能与任务所需的属性冲突。
grunt.initConfig({
concat: {
// concat 任务的配置
},
uglify: {
// uglify 任务的配置
},
// 其他与任务无关的属性
my_property: 'whatever',
my_src_files: ['foo/*.js', 'bar/*.js'],
});
任务配置和目标
当任务运行时,Grunt 会从与其同名的属性中查找配置。多重任务可以有多个配置,每个任务使用任意命名的目标定义。例如,concat
任务有 foo
和 bar
两个目标,而 uglify
任务只有 bar
一个目标:
grunt.initConfig({
concat: {
foo: {
// concat 任务的目标 "foo"
},
bar: {
// concat 任务的目标 "bar"
},
},
uglify: {
bar: {
// uglify 任务的目标 "bar"
},
},
});
运行 grunt concat:foo
或 grunt concat:bar
只会处理指定的目标配置,而运行 grunt concat
则会依次处理所有目标。
选项
在任务配置中,options
属性可用于覆盖默认值。每个目标都可以有独立的 options
属性。目标级的选项会覆盖任务级的选项。
grunt.initConfig({
concat: {
options: {
// 任务级的选项,覆盖任务的默认值
},
foo: {
options: {
// 目标 "foo" 的选项,覆盖任务级的选项
},
},
bar: {
// 没有定义选项,使用任务级的选项
},
},
});
文件
所有文件格式都支持 src
和 dest
属性,"简洁格式" 与 "文件数组格式" 还支持以下属性:
filter
用于匹配src
文件路径,传入 fs.Stats 方法名或自定义函数,返回true
或false
。nonull
当一个匹配没有被检测到时,返回一个包含模式自身的列表。否则,如果没有任何匹配项时,则返回一个空列表。dot
允许模式匹配以句点开头的文件名。matchBase
不带斜线的模式将不会匹配包含在斜线中的文件名。比如,a?b 匹配路径/xyz/123/acb
但不匹配/xyz/acb/123
。expand
处理动态的 src-dest 映射。详见 动态构建文件对象。- 查看 node-glob 与 minimatch 文档获取更多信息。
简洁文件格式
每个目标只有一个 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',
},
},
});
文件对象格式
每个目标可以有多个 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'],
},
},
},
});
文件数组格式
每个目标可以有多个 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'},
],
},
},
});
自定义过滤函数
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);
},
},
},
});
通配符模式
*
匹配任意数量的字符,除了/
?
匹配单个字符,除了/
**
匹配任意数量的字符,包括/
{}
以逗号分割的"或"表达式列表!
匹配取反
例如,foo/*.js
会匹配所有 foo/
目录下以 .js
结尾的文件, 而 foo/**/*.js
会匹配所有 foo/
目录及其子目录下以 .js
结尾的文件。
例子:
// 单个文件
{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: ...}
动态构建文件对象
当处理大量的单个文件时,一些附加的属性可以用来动态地构建文件列表。
expand
设为 true
用于启用以下选项:
cwd
所有src
的匹配都是相对于当前路径,但不包括当前路径。src
相对于cwd
路径的匹配模式。dest
目标路径的前缀。ext
使用这个属性值替换生成的dest
路径中所有文件的扩展名。extDot
用于指定扩展名点号的位置。可以设为'first'
(扩展名始于文件名的第一个点号)或'last'
(扩展名始于文件名的最后一个点号),默认为'first'
。[0.4.3 新增]flatten
从生成的dest
路径中移除所有的路径部分。rename
在执行ext
和flatten
之后,对每个匹配的src
文件调用这个函数。传入dest
和匹配的src
路径,返回一个新的dest
值。如果返回相同的dest
不止一次,每个使用它的src
来源都将被添加到一个数组中。
在下面的例子中,static_mappings
和 dynamic_mappings
两个目标中查找到的文件映射列表是相同的,这是因为任务运行时 Grunt 会自动将 dynamic_mappings
文件对象扩展为与 static_mappings
一致的静态文件映射。
grunt.initConfig({
uglify: {
static_mappings: {
// 静态文件映射,
// 添加或删除文件时需要更新 Gruntfile。
files: [
{src: 'lib/a.js', dest: 'build/a.min.js'},
{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: {
// 动态文件映射,
// 当任务运行时会自动在 "lib/" 目录下查找 "**/*.js" 并构建文件映射,
// 添加或删除文件时不需要更新 Gruntfile。
files: [
{
expand: true, // 启用动态扩展
cwd: 'lib/', // 源文件匹配都相对此目录
src: ['**/*.js'], // 匹配模式
dest: 'build/', // 目标路径前缀
ext: '.min.js', // 目标文件路径中文件的扩展名
extDot: 'first' // 扩展名始于文件名的第一个点号
},
],
},
},
});
模板
模版使用 <% %>
分隔符定义,当任务从配置读取时会自动进行扩展。模板会被递归地扩展,直到全部扩展完成。
模版的处理都是在整个配置对象的上下文环境中的。因此,可以在模板中使用 grunt
方法,比如:<%= grunt.template.today('yyyy-mm-dd') %>
。
<%= prop.subprop %>
扩展配置中prop.subprop
的值,无论什么数据类型。不仅可以引用字符串值,也可以是数组或其他对象。<% %>
执行任意内联的 JavaScript 代码。可用于控制流或循环。
下面的例子中,运行 grunt concat:sample
时会拼接 banner
中的 /* abcde */
与 foo/*.js
+ bar/*.js
+baz/*.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'],
});
导入外部数据
下面的例子中,项目的元数据是从 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'
}
}
});