配置任务 Configuring Tasks
目录
本指南介绍了如何在项目中使用文件 Gruntfile 配置任务。如果你不知道 Gruntfile 是什么,请阅读 Grunt 入门指南,并查看 Gruntfile 示例。
1. Grunt 配置 ⬆
任务配置通过 Gruntfile 中的 grunt.initConfig
指定。配置通常挂在以任务命名的属性上,但是可以包含任意数据。只要这些属性与任务需要的属性不冲突,否则会被忽略。
另外,因为是在 javaScript 文件中,就不局限于 JSON;你可以使用任何有效的 JavaScript。如有必要,你设置可以以编程的方法生成配置。
grunt.initConfig({
concat: {
// concat task configuration goes here.
},
uglify: {
// uglify task configuration goes here.
},
// Arbitrary non-task-specific properties.
my_property: 'whatever',
my_src_files: ['foo/*.js', 'bar/*.js'],
});
2. 任务配置和目标 ⬆
Task 和 Target 似乎没必要翻译
当一个任务运行时,Grunt 在同名属性下查找该任务的配置。多个任务可以有多个配置,定义在任意命名的 "targets" 中。在下面的例子中,任务 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.
},
},
});
同时指定一个任务和目标,例如 grunt concat:foo
或 grunt concat:bar
将只处理指定目标的配置,而运行 grunt concat
则会遍历所有的目标,顺序处理。注意,如果一个任务已经通过 grunt.renameTask 重命名,Grunt 将在配置对象中查找以新任务名命名的属性。
3. 选项 ⬆
在一个任务配置中,可以指定属性 options
来覆盖内置的默认子。此外,每个目标可以含有一个特定该目标的 options
属性。Target 级别的选项将覆盖任务界别的选项。
对象 options
时可选的,如果不需要的话还可以省略它。
grunt.initConfig({
concat: {
options: {
// Task-level options may go here, overriding task defaults.
},
foo: {
options: {
// "foo" target options may go here, overriding task-level options.
},
},
bar: {
// No options specified; this target will use task-level options.
},
},
});
4. 文件集合 ⬆
因为大部分任务执行的是文件操作,Grunt 拥有强大的抽象,用于声明任务应该操作哪些文件。有几种方式来定义 src-dest (源-目标) 文件映射,提供了不同程度的冗余和控制。任何任务都会明白以下所有格式,所以选择最能满足你的需求的格式。
所有文件都支持 src
和 dest
,但是“紧凑型”和“文件数组”格式支持一些额外的属性:
filter
可以是一个有效的 fs.Stats 方法名,也可以是一个函数,接受匹配的文件路径src
,并返回true
或false
。nonull
当没有找到任何匹配文件时,返回含有通配符的列表。否则,如果没有任何匹配文件,则返回一个空列表。结合 Grunt--verbose
标记,该选项可以帮助调试文件路径问题。dot
允许通配符匹配以一段字符开头的文件名,即使是通配符没有明确指定那段字符的位置。matchBase
如果设置了属性,不含斜杠的模式将不配路径名,如果该路径还有斜杠。例如,模式 a?b 将匹配路径/xyz/123/acb
,但是不匹配/xyz/acb/123
。expand
处理一个动态的源文件-目标文件的映射,更多信息请查看“动态构建文件集合对象”。- 其他属性会被作为匹配选项传递到底层库。更多选项查看文档 node-glob 和 minimatch。
4.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',
},
},
});
4.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'],
},
},
},
});
4.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'},
],
},
},
});
4.4 旧格式 ⬆
文件格式 dest-as-target 多任务和多目标存在之前的剩余物,即目标文件就是目标名。不幸的是,由于目标名是文件路径,运行 grunt task:target
可能是尴尬的。此外,你不能执行目标级别的选项,或者为每对 src-dest 文件映射指定额外的属性。
思考一下这种过时的格式,并在可能的情况下避免它。
grunt.initConfig({
concat: {
'dest/a.js': ['src/aa.js', 'src/aaa.js'],
'dest/b.js': ['src/bb.js', 'src/bbb.js'],
},
});
4.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);
},
},
},
});
4.6 匹配模式 ⬆
单独指定所有的源文件路径,往往是不切实际的,所以 Grunt 通过内置的 node-glob 和 minimatch 库支持文件名扩展(也称为通配符)。
虽然这不是一个全面的匹配模式指南,但是要知道,在一个文件路径中:
*
匹配任意数量的字符,但是不匹配/
?
匹配单个字符,但是不匹配/
**
匹配任意数量的字符,包括/
,只要它是唯一的路径部分{}
允许用逗号分割的“或”表达式列表!
在模式的开始处,将对匹配取反
大多数人都需要知道的是,foo/*.js
将匹配子目录 foo/
中所有以 .js
结尾的文件,但是 foo/**/*.js
将匹配子目录 foo/
和它的所有子目录中所有以 .js
结尾的文件。
此外,为了简化复杂的模式匹配,Grunt 允许指定文件路径数组或匹配模式。模式被顺序处理,以 !
为前缀的模式剔除结果集中匹配的文件。结果集是唯一的。
For example:
// You can specify single files:
{src: 'foo/this.js', dest: ...}
// Or arrays of files:
{src: ['foo/this.js', 'foo/that.js', 'foo/the-other.js'], dest: ...}
// Or you can generalize with a glob pattern:
{src: 'foo/th*.js', dest: ...}
// This single node-glob pattern:
{src: 'foo/{a,b}*.js', dest: ...}
// Could also be written like this:
{src: ['foo/a*.js', 'foo/b*.js'], dest: ...}
// All .js files, in foo/, in alpha order:
{src: ['foo/*.js'], dest: ...}
// Here, bar.js is first, followed by the remaining files, in alpha order:
{src: ['foo/bar.js', 'foo/*.js'], dest: ...}
// All files except for bar.js, in alpha order:
{src: ['foo/*.js', '!foo/bar.js'], dest: ...}
// All files in alpha order, but with bar.js at the end.
{src: ['foo/*.js', '!foo/bar.js', 'foo/bar.js'], dest: ...}
// Templates may be used in filepaths or glob patterns:
{src: ['src/<%= basename %>.js'], dest: 'build/<%= basename %>.min.js'}
// But they may also reference file lists defined elsewhere in the config:
{src: ['foo/*.js', '<%= jshint.all.src %>'], dest: ...}
For more on glob pattern syntax, see the node-glob and minimatch documentation.
关于匹配模式语法的更新信息,请查看 node-glob 和 minimatch 文档。
4.7 动态创建文件对象 ⬆
似乎应该保留 files,因为属性名就是 files
当你要处理许多单独文件时,一些额外的属性可以用来动态的创建一个文件列表。这些属性可能被指定在映射格式“紧凑型”和“文件数组”中。
expand
设置为 true,以启用以下选项:cwd
所有src
相对于(但不包括)该路径进行匹配。src
匹配模式,相对于cwd
。dest
目标路径前缀。ext
在生成的dest
路径中替换任何现有的扩展名。flatten
从生成的dest
路径中移除所有的路径部分。rename
为每个匹配的src
文件调用该函数,(在扩展名重命名和扁平化之后)。dest
和匹配的src
被转入,该函数必须返回一个新dest
值。如果多次返回同样的dest
,使用它的每个src
将被添加到它一个源数组中。
在下面的例子中,任务 minify
将得到相同的源-目标文件映射列表,对于目标 static_mapping
和 dynamic_mapping
,因为 Grunt 将自动扩展 dynamic_mappings
文件对象为 4 个独立的静态的源-目标文件映射,假设任务运行时只找到 4 个文件。
可以指定任意组合的静态和动态的源-目标文件映射。
grunt.initConfig({
minify: {
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: '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 "minify" 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: [
{
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.
},
],
},
},
});
5. 模板 ⬆
使用分隔符 <% %>
指定的模板将被自动扩展,当任务从配置中读取它们时。模板被递归扩展直到没有剩余。
整个配置对象是上下文,在使用的属性下的。此外,在模板中,grunt
和它的方法也是有效的,例如 <%= grunt.template.today('yyyy-mm-dd') %>
。
<%= prop.subprop %>
扩展为配置中prop.subprop
的值。像这样的模板可能用来不仅仅引用字符串值,也可以是数组或其他对象。<% %>
执行任意的内联 JavaScript 代码。对于控制流程或循环非常有用。
下面给定简单任务 concat
的配置,运行 grunt concat:sample
将生成一个命名为 build/abcde.js
的文件,通过合并 /* abcde */
和所有匹配 foo/*.js
+ bar/*.js
+ baz/*.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'
},
},
// Arbitrary properties used in task configuration templates.
foo: 'c',
bar: 'b<%= foo %>d', // 'bcd'
baz: 'a<%= bar %>e', // 'abcde'
qux: ['foo/*.js', 'bar/*.js'],
});
6. 导入外部数据 ⬆
在下面的 Gruntfile 中,项目元数据从一个 package.json
文件被导入到 Grunt 配置,并且 grunt-contrib-uglify 插件任务被配置为压缩源文件并且使用元数据动态生成一段顶部注释。
Grunt 拥有方法 grunt.file.readJSON
and 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'
}
}
});