manlili blog

grunt配置

本篇主要讲在Gruntfile文件配置。

任务配置

假设我需要创建concat和uglify两个JSON格式的任务以及my_property字符串格式任务和my_src_files数组格式的任务
直接举个例子:

1
2
3
4
5
6
7
8
9
10
11
grunt.initConfig({
concat: {
// 这里是concat任务的配置信息。
},
uglify: {
// 这里是uglify任务的配置信息
},
// 任意数据。
my_property: 'whatever',
my_src_files: ['foo/*.js', 'bar/*.js'],
});

从上图可知:由于这本身就是JavaScript,因此你不仅限于使用JSON;你可以在这里使用任何有效的JavaScript。必要的情况下,你甚至可以以编程的方式生成配置。

注意:当运行一个任务时,Grunt会自动查找配置对象中的同名属性。

目标配置

目标就是每个任务需要执行的目标,举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
grunt.initConfig({
concat: {
foo: {
// foo目标
},
bar: {
// bar目标
},
},
uglify: {
bar: {
// bar目标
},
},
});

在上面的案例中,concat任务有名为foo和bar两个目标,而uglify任务仅仅只有一个名为bar目标。
我们可以执行特定的目标,比如直接在文件夹里右键直接调出gitBash,执行如下命令:

1
grunt concat:foo或者grunt concat:bar

如果我们使用了grunt concat命令,则将遍历所有目标(foo目标,bar目标)并依次处理。

options属性

options对象是可选的,如果不需要,可以忽略。

需要注意:
(1)在一个任务配置中,options属性可以用来指定覆盖内置属性的默认值。
(2)此外,每一个目标中还可以设置专有options属性。
(3)目标里面的options将会覆盖任务级的options。
举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
grunt.initConfig({
concat: {
options: {
// 这里是任务级的Options,覆盖默认值
},
foo: {
options: {
// foo目标的options,优先级别大于任务级option
},
},
bar: {
// 不设置options
},
},
});

src-dest配置

每个任务都有src-dest(源文件-目标文件),当然dest可以没有。
比如jshint插件是验证JS语法的,错误的信息都直接显示在console上面,无须专门创建个dest文件。

(1)src-dest数组格式
这种方式比较直观,建议使用此方法。

举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
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)src-dest文件对象格式
好处:
(1)每个目标对应多个src-dest形式的文件映射
(2)key就是目标文件,value就是源文件
(3)源文件一般需要用数组

举个例子:

1
2
3
4
5
6
7
8
9
10
grunt.initConfig({
concat: {
foo: {
files: {
'dest/a.js': ['src/aa.js', 'src/aaa.js'],
'dest/a1.js': ['src/aa1.js', 'src/aaa1.js'],
}
}
},
});

或者:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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'},
],
},
},
});

过滤函数配置

可有可无,看自己需要。

比如node的模块系统fs里面isFile是检查是否是文件的方法,举个过滤器的例子:

1
2
3
4
5
6
7
8
grunt.initConfig({
clean: {
foo: {
src: ['tmp/**/*'],
filter: 'isFile' //此处是过滤器
},
},
});

或者创建你自己的filter函数,根据文件是否匹配来返回true或者false。
下面的例子将仅仅清理一个空目录:

1
2
3
4
5
6
7
8
9
10
grunt.initConfig({
clean: {
foo: {
src: ['tmp/**/*'],
filter: function(filepath) {
return (grunt.file.isDir(filepath) && require('fs').readdirSync(filepath).length === 0);
},
},
},
});

文件路径配置

src-dest里面需要用到文件路径,通常分别指定所有源文件路径是不切实际的。

(1)通配符模式
通常分别指定所有源文件路径是不切实际的,但是我们可以用grunt提供的简写符,类似于正则里面的各种元字符,下面来看看:

1
2
3
4
5
① * 匹配任意数量的字符,但不匹配 /
② ? 匹配单个字符,但不匹配 /
③ ** 匹配任意数量的字符,包括 /,只要它是路径中唯一的一部分
④ {} 允许使用一个逗号分割的“或”表达式列表
⑤ ! 在模式的开头用于排除一个匹配模式所匹配的任何文件

比如:

1
2
foo/*.js将匹配位于foo/目录下的所有的.js结尾的文件
foo/**/*js将匹配foo/目录以及其子目录中所有以.js结尾的文件

具体举个代码例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 指定单个文件:
{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: ...}

(2)模板模式
①使用内部数据的模板
格式是

1
<% %>

举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
grunt.initConfig({
//用于任务配置模板的任意属性
foo: 'c',
bar: 'b<%= foo %>d', // 'bcd',
baz: 'a<%= bar %>e', // 'abcde',
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'
},
},
qux: ['foo/*.js', 'bar/*.js'],
});

②导入外部数据的模板
假设想引入package.json里面的数据,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"name": "grunt-test",
"version": "1.0.0",
"description": "grunt test exemple",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"grunt"
],
"devDependencies": {
"grunt": "^1.0.1",
"grunt-contrib-uglify": "^2.2.0"
},
"author": "manlili",
"license": "ISC"
}
```grunt.file.readJSON
那么只要在grunt.initConfig顶部引用grunt.file.readJSON就可以了,代码如下:
```bash
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'
}
}
});

动态构建文件对象(选读)

当你希望处理大量的单个文件时,这里有一些附加的属性可以用来动态的构建一个文件列表。这些属性都可以用于Compact和Files Array文件映射格式。

expand 设置为true用于启用下面的选项:

  • cwd:所有src指定的匹配都将相对于此处指定的路径(但不包括此路径)。
  • src:相对于cwd路径的匹配模式。
  • dest:目标文件路径前缀。
  • ext:对于生成的dest路径中所有实际存在文件,均使用这个属性值替换扩展名。
  • extDot:用于指定标记扩展名的英文点号的所在位置。可以赋值 ‘first’ (扩展名从文件名中的第一个英文点号开始) 或 ‘last’ (扩展名从最后一个英文点号开始),默认值为 ‘first’ [添加于 0.4.3 版本]
  • flatten:从生成的dest路径中移除所有的路径部分。
  • rename:对每个匹配的src文件调用这个函数(在重命名后缀和移除路径之后)。dest和匹配的src路径将被作为参数传入,此函数应该返回一个新的dest值。 如果相同的dest返回不止一次,那么,每个返回此值的src来源都将被添加到一个数组中作为源列表。

举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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: '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: [
{
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
},
],
},
},
});

请我喝杯果汁吧!