• 配置任务
    • Grunt配置
    • 任务配置和目标
    • options
    • 文件
      • 简洁格式
      • 文件对象格式
      • 文件数组格式
      • 较老的格式
      • 自定义过滤函数
      • 通配符模式
      • 构建动态文件对象
      • 模板
    • 导入外部数据

    配置任务

    这个指南解释了如何使用Gruntfile来为你的项目配置任务。如果你还不知道Gruntfile是什么,请先阅读新手上路指南并参考Gruntfile示例。

    Grunt配置

    Grunt的任务配置都是在你Gruntfile中的grunt.initConfig方法中指定。这个配置主要都是一些命名任务属性(通常任务都被定义为一个对象传递给grunt.initConfig方法, 而任务都是作为这个对象的属性定义的),也可以包含任意其他数据。但这些属性(其他属性)不能与你的任务所需要的属性相冲突,否则它将被忽略(一般情况下任务中的属性命名都是约定俗成的)。

    此外,由于这本身就是JavaScript,因此你不仅限于使用JSON;你可以在这里使用任何有效的JavaScript。必要的情况下,你甚至可以以编程的方式生成配置(比如通过其他的程序生成一个或多个任务配置)。

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

    任务配置和目标

    当运行一个任务时,Grunt会自动查找配置对象中的同名属性。多个任务可以有多个配置,每个任务可以使用任意的命名’targets’来定义多个任务目标。在下面的例子中,concat任务有名为foobar两个目标,而uglify任务仅仅只有一个名为bar目标。

    1. grunt.initConfig({
    2. concat: {
    3. foo: {
    4. // 这里是concat任务'foo'目标的选项和文件
    5. },
    6. bar: {
    7. // 这里是concat任务'bar'目标的选择和文件
    8. }
    9. },
    10. uglify: {
    11. bar: {
    12. // 这里是uglify任务'bar'目标的选项和文件
    13. }
    14. }
    15. });

    指定一个像grunt concat:foo或者grunt concat:bar的任务和目标只会处理指定的任务目标配置,而运行grunt concat将遍历所有的(定义在concat任务中的)目标并依次处理。注意,如果一个任务使用grunt.renameTask重命名过,Grunt将在配置对象中查找新的任务名称属性。

    options

    在一个任务配置中,options属性可以用来指定覆盖属性的内置默认值。此外,每一个任务目标中更具体的目标都可以拥有一个options属性。目标级的选项将会覆盖任务级的选项(就近原则————options离目标越近,其优先级越高)。

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

    1. grunt.initConfig({
    2. concat: {
    3. options: {
    4. // 这里是任务级的Options,覆盖任务的默认值
    5. },
    6. foo: {
    7. options: {
    8. // 这里是'foo'目标的options,它会覆盖任务级的options.
    9. }
    10. },
    11. bar: {
    12. // 没有指定options,这个目标将使用任务级的options
    13. }
    14. }
    15. });

    文件

    由于大多数的任务执行文件操作,Grunt有一个强大的抽象声明说明任务应该操作哪些文件。这里有好几种定义src-dest(源文件-目标文件)文件映射的方式,都提供了不同程度的描述和控制操作方式。任何一种多任务(包含多个任务目标的任务)都能理解下面的格式,所以你只需要选择满足你需求的格式就行。

    所有的文件格式都支持srcdest属性,此外”Compact”[简洁]和”Files Array”[文件数组]格式还支持以下一些附加的属性:

    • filter 它通过接受任意一个有效的fs.Stats方法名或者一个函数来匹配src文件路径并根据匹配结果返回true或者false

    • nonull 当一个匹配没有被检测到时,它返回一个包含模式自身的列表。否则,如果没有任何匹配项时它返回一个空列表。结合Grunt的--verbore标志, 这个选项可以帮助用来调试文件路径的问题。

    • dot 它允许模式模式匹配句点开头的文件名,即使模式并不明确文件名开头部分是否有句点。

    • matchBase 如果设置这个属性,缺少斜线的模式(意味着模式中不能使用斜线进行文件路径的匹配)将不会匹配包含在斜线中的文件名。 例如,a?b将匹配/xyz/123/acb但不匹配/xyz/acb/123

    • expand 处理动态的src-dest文件映射,更多的信息请查看“动态构建文件对象”。

    • 其他的属性将作为匹配项传递给底层的库。在node-glob和minimatch文档中可以查看更多选项。

    简洁格式

    这种形式允许每个目标对应一个src-dest文件映射。通常情况下它用于只读任务,比如grunt-contrib-jshint, 它就值需要一个单一的src属性,而不需要关联的dest选项. 这种格式还支持为每个src-dest文件映射指定附加属性。

    1. grunt.initConfig({
    2. jshint: {
    3. foo: {
    4. src: ['src/aa.js', 'src/aaa.js']
    5. }
    6. },
    7. concat: {
    8. bar: {
    9. src: ['src/bb.js', 'src/bbb.js'],
    10. dest: 'dest/b.js'
    11. }
    12. }
    13. });

    文件对象格式

    这种形式支持每个任务目标对应多个src-dest形式的文件映射,属性名就是目标文件,源文件就是它的值(源文件列表则使用数组格式声明)。可以使用这种方式指定数个src-dest文件映射, 但是不能够给每个映射指定附加的属性。

    1. grunt.initConfig({
    2. concat: {
    3. foo: {
    4. files: {
    5. 'dest/a.js': ['src/aa.js', 'src/aaa.js'],
    6. 'dest/a1.js': ['src/aa1.js', 'src/aaa1.js']
    7. }
    8. },
    9. bar: {
    10. files: {
    11. 'dest/b.js': ['src/bb.js', 'src/bbb.js'],
    12. 'dest/b1.js': ['src/bb1.js', 'src/bbb1.js']
    13. }
    14. }
    15. }
    16. });

    文件数组格式

    这种形式支持每个任务目标对应多个src-dest文件映射,同时也允许每个映射拥有附加属性:

    1. grunt.initConfig({
    2. concat: {
    3. foo: {
    4. files: [
    5. {src: ['src/aa.js', 'src/aaa.js'], dest: 'dest/a.js'},
    6. {src: ['src/aa1.js', 'src/aaa1.js'], dest: 'dest/a1.js'}
    7. ]
    8. },
    9. bar: {
    10. files: [
    11. {src: ['src/bb.js', 'src/bbb.js'], dest: 'dest/b/', nonull: true},
    12. {src: ['src/bb1.js', 'src/bbb1.js'], dest: 'dest/b1/', filter: 'isFile'}
    13. ]
    14. }
    15. }
    16. });

    较老的格式

    dest-as-target文件格式在多任务和目标形式出现之前是一个过渡形式,目标文件路径实际上就是目标名称。遗憾的是, 由于目标名称是文件路径,那么运行grunt task:target可能不合适。此外,你也不能指定一个目标级的options或者给每个src-dest文件映射指定附加属性。

    1. grunt.initConfig({
    2. concat: {
    3. 'dest/a.js': ['src/aa.js', 'src/aaa.js'],
    4. 'dest/b.js': ['src/bb.js', 'src/bbb.js']
    5. }
    6. });

    自定义过滤函数

    filter属性可以给你的目标文件提供一个更高级的详细帮助信息。只需要使用一个有效的fs.Stats方法名。下面的配置仅仅清理一个与模式匹配的真实的文件:

    1. grunt.initConfig({
    2. clean: {
    3. foo: {
    4. src: ['temp/**/*'],
    5. filter: 'isFile'
    6. }
    7. }
    8. });

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

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

    通配符模式

    原文档标题为Globbing patterns,大意是指使用一些通配符形式的匹配模式快速的匹配文件。

    通常分别指定所有源文件路径的是不切实际的(也就是将源文件-目标文件一一对应的关系列出来),因此Grunt支持通过内置的node-glob和minimatch库来匹配文件名(又叫作globbing)。

    当然这并不是一个综合的匹配模式方面的教程,你只需要知道如何在文件路径匹配过程中使用它们即可:

    • *匹配任意数量的字符,但不匹配/

    • ?匹配单个字符,但不匹配/

    • **匹配任意数量的字符,包括/,只要它是路径中唯一的一部分

    • {}允许使用一个逗号分割的列表或者表达式

    • !在模式的开头用于否定一个匹配模式(即排除与模式匹配的信息)

    大多数的人都知道foo/*.js将匹配位于foo/目录下的所有的.js结尾的文件, 而foo/**/*.js将匹配foo/目录以及其子目录中所有以.js结尾的文件。

    此外, 为了简化原本复杂的通配符模式,Grunt允许指定一个数组形式的文件路径或者一个通配符模式。模式处理的过程中,带有!前缀模式不包含结果集中与模式相配的文件。 而且其结果集也是唯一的。

    示例:

    1. //可以指定单个文件
    2. {src: 'foo/this.js', dest: …}
    3. //或者指定一个文件数组
    4. {src: ['foo/this.js', 'foo/that.js', 'foo/the-other.js'], dest: …}
    5. //或者使用一个匹配模式
    6. {src: 'foo/th*.js', dest: …}
    7. //一个独立的node-glob模式
    8. {src: 'foo/{a,b}*.js', dest: …}
    9. //也可以这样编写
    10. {src: ['foo/a*.js', 'foo/b*.js'], dest: …}
    11. //foo目录中所有的.js文件,按字母排序
    12. {src: ['foo/*js'], dest: …}
    13. //这里首先是bar.js,接着是剩下的.js文件按字母排序
    14. {src: ['foo/bar.js', 'foo/*.js'], dest: …}
    15. //除bar.js之外的所有的.js文件,按字母排序
    16. {src: ['foo/*.js', '!foo/bar.js'], dest: …}
    17. //所有.js文件按字母排序, 但是bar.js在最后.
    18. {src: ['foo/*.js', '!foo/bar.js', 'foo/bar.js'], dest: …}
    19. //模板也可以用于文件路径或者匹配模式中
    20. {src: ['src/<%= basename %>.js'], dest: 'build/<%= basename %>.min.js'}
    21. //它们也可以引用在配置中定义的其他文件列表
    22. {src: ['foo/*.js', '<%= jshint.all.src %>'], dest: …}

    可以在node-glob和minimatch文档中查看更多的关于通配符模式的语法。

    构建动态文件对象

    当你希望处理大量的单个文件时,这里有一些附加的属性可以用来动态的构建一个文件. 这些属性都可以指定在CompactFiles Array映射格式中(这两种格式都可以使用)。

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

    • cwd 相对于当前路径所匹配的所有src路径(但不包括当前路径。)

    • src 相对于cwd路径的匹配模式。

    • dest 目标文件路径前缀。

    • ext 使用这个属性值替换生成的dest路径中所有实际存在文件的扩展名(比如我们通常将压缩后的文件命名为.min.js)。

    • flatten 从生成的dest路径中移除所有的路径部分。

    • rename 对每个匹配的src文件调用这个函数(在执行extflatten之后)。传递dest和匹配的src路径给它,这个函数应该返回一个新的dest值。 如果相同的dest返回不止一次,每个使用它的src来源都将被添加到一个数组中。

    在下面的例子中,minify任务将在static_mappingsdynamic_mappings两个目标中查看相同的src-dest文件映射列表, 这是因为任务运行时Grunt会自动展开dynamic_mappings文件对象为4个单独的静态src-dest文件映射—假设这4个文件能够找到。

    可以指定任意结合的静态src-dest和动态的src-dest文件映射。

    1. grunt.initConfig({
    2. minify: {
    3. static_mappings: {
    4. //由于这里的src-dest文件映射时手动指定的, 每一次新的文件添加或者删除文件时,Gruntfile都需要更新
    5. files: [
    6. {src: 'lib/a.js', dest: 'build/a.min.js'},
    7. {src: 'lib/b.js', dest: 'build/b.min.js'},
    8. {src: 'lib/subdir/c.js', dest: 'build/subdir/c.min.js'},
    9. {src: 'lib/subdir/d.js', dest: 'build/subdir/d.min.js'}
    10. ]
    11. },
    12. dynamic_mappings: {
    13. //当'minify'任务运行时Grunt将自动在"lib/"下搜索"**/*.js", 然后构建适当的src-dest文件映射,因此你不需要在文件添加或者移除时更新Gruntfile
    14. files: [
    15. {
    16. expand: true, //启用动态扩展
    17. cwd: 'lib/', //批匹配相对lib目录的src来源
    18. src: '**/*.js', //实际的匹配模式
    19. dest: 'build/', //目标路径前缀
    20. ext: '.min.js' //目标文件路径中文件的扩展名.
    21. }
    22. ]
    23. }
    24. }
    25. });

    模板

    使用<% %>分隔符指定的模板会在任务从配置中读取相应的数据时将自动填充。模板会以递归的方式填充,直到配置中不再存在遗留模板相关的信息(与模板匹配的)。

    整个配置对象决定了属性上下文(模板中的属性)。此外,在模板中使用grunt以及它的方法都是有效的,例如: <%= grunt.template.today('yyyy-mm-dd') %>

    • <%= prop.subprop %> 将会自动展开配置信息中的prop.subprop的值,不管是什么类型。像这样的模板不仅可以用来引用字符串值,还可以引用数组或者其他对象类型的值。

    • <% %>执行任意内联的JavaScript代码,对于控制流或者循环来说是非常有用的。

    下面提供了一个concat任务配置示例,运行grunt concat:sample时将通过banner中的/* abcde */连同foo/*.js+bar/*.js+bar/*.js匹配的所有文件来生成一个名为build/abcde.js的文件。

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

    导入外部数据

    在下面的Gruntfile中,项目的元数据是从package.json文件中导入到Grunt配置中的,并且grunt-contrib-uglify插件的uglify任务被配置用于压缩一个源文件以及使用该元数据动态的生成一个banner注释。

    Grunt有grunt.file.readJSONgrunt.file.readYAML两个方法分别用于引入JSON和YAML数据。

    1. grunt.initConfig({
    2. pkg: grunt.file.readJSON('package.json'),
    3. uglify: {
    4. options: {
    5. banner: '/* <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
    6. },
    7. dist: {
    8. src: 'src/<%= pkg.name %>.js',
    9. dest: 'dist/<%= pkg.name %>.min.js'
    10. }
    11. }
    12. });