Grunt 入门教程二:配置任务

2.1 Grunt 配置

任务配置都定义在GruntFile 文件中的 grunt.initConfig 方法中。这个配置一般都是一些以任务名命名的属性,但是也可以包含任意的数据。如果一个属性没有被任何任务用到,就会被忽略。

而且,因为这是 JavaScript 文件,任何合法的 JS 代码都可以写,而不是仅仅局限于 JSON。如果有必要,你甚至可以用代码动态生成配置。

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.2 任务配置和任务目标

当一个任务运行时,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 会在config对象中寻找新的名字命名的属性。

2.3 默认配置

在一个任务配置里,可以通过 options 属性来覆盖默认配置。任务中的每一个目标也都可以有一个与之对应的 options 属性。目标中的options配置会覆盖任务中的options。

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.
    },
  },
});


2.4 文件

因为大部分的任务都是执行文件操作,所以Grunt对所要操作的文件有很强的抽象。有几种方式可以实现源文件到目标文件的映射,可以有多级的冗余和控制(不太好翻译)。任何一种多任务都可以理解下面的这些格式,所以你可以使用任何最合适的格式。

所有的文件的格式都支持”src“和”dest“,但是”简洁“和”文件数组“两种格式还支持如下一些附加属性

  • filter:过滤器,任意一个合法的 fs.stats 方法名(http://nodejs.org/docs/latest/api/fs.html#fs_class_fs_stats),或者任何一个接受 src 作为文件路径并返回 True 或者 False的方法都可以。
  • nonull:非空,如果没有任何一个匹配被找到,那么就返回一个包含这个模式本身的列表。否则,返回一个空列表。这个选项可以结合grunt的 --verbose 参数来帮助调试文件路径问题。
  • dot:可以让模式匹配一个以句点开头的文件名,即使模式没有显式地指定一个句点。
  • matchBase:只匹配base路径,如果设置了这个参数,那么不会匹配子目录。比如 a?b 会匹配 /xyz/123/acb 但是不会匹配 /xyz/acb/123。
  • expand:拓展,执行一个动态的 源文件到目标文件的映射,参见“Building the files object dynamically”。
  • 其他所有的参数都会被当做配置参数传给底层库,参见 node-glob (https://github.com/isaacs/node-glob) 和 minimatch(https://github.com/isaacs/minimatch).

2.5 简洁格式

这种模式一般用在只读任务中,只需要一个 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.6 文件对象格式

这种格式可以在一个目标中配置多个 源文件到目标文件的映射。属性名是目标文件,属性值是源文件。对每个目标文件可以定义任意数量的源文件,但是不支持附加属性

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.7 文件数组格式

这种格式也可以在一个目标中配置多个 源文件到目标文件的映射。而且可以使用附加属性。

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.8 过时的格式

下面这个是在多任务和多目标出现之前的一种过时的格式,这种配置的目标文件路径实际上是目标名,所以会导致 grunt task:target 这样的命令出错,不建议使用这种格式。

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


2.9 自定义的过滤方法

filter 属性可以帮你定义很高级的文件细节。最简单的,可以直接使用一个 fs.Stats 方法名。下面这段代码只会匹配真实的文件。

grunt.initConfig({
  clean: {
    foo: {
      src: ['tmp/**/*'],
      filter: 'isFile',
    },
  },
});


或者你可以创建一个自己的方法,对于应该被匹配的文件返回 true,对于不该被匹配的文件返回false。比如下面这个例子只会匹配到空文件夹。

grunt.initConfig({
  clean: {
    foo: {
      src: ['tmp/**/*'],
      filter: function(filepath) {
        return (grunt.file.isDir(filepath) && require('fs').readdirSync(filepath).length === 0);
      },
    },
  },
});


2.10 globbing 模式(不太好翻译,类似正则式)

有时候很难把所有的源文件都一一列举出来,所以 Grunt 支持 通过 node-glob(https://github.com/isaacs/node-glob) 和 minimatch(https://github.com/isaacs/minimatch) 来进行文件名描述(又称 globbing)。

这不是一个很好理解的 globbing 模式教程,在一个文件路径中:

  • "*" 匹配任意字符,除了 "/"
  • "?" 匹配按个字符,除了"/"
  • "**" 匹配任意字符,包括"/"
  • "{}" 一个以 逗号分隔的 “或”逻辑
  • "!" 在模式的开头表示否定。

大家都知道,foo/*.js 会匹配 foo/ 目录下以 .js 结尾的任何文件(但是不包括子目录),而 foo/**/*.js 会匹配foo以及其子目录下的任何以 .js 结尾的文件。

并且,为了简化复杂的globbing 模式,Grunt 允许在一个列表中写多个 globbing 模式。这些模式会按顺序被处理。以 "!" 开头的会被排除。

// 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: ...}


关于 glob 模式语法,参见 node-glob(https://github.com/isaacs/node-glob) 和 minimatch(https://github.com/isaacs/minimatch)


2.11 动态创建文件

如果你想处理大量的单个文件,可以用一些附加属性来帮助动态创建文件。这些属性在“简洁格式“和”文件数组格式“下都可用。

  • expand:设为 true 来启用下面这些属性。
  • cwd:所有的 src 都相对于此路径(但是不包含)。
  • src:需要匹配的模式,相对于cwd。
  • dest:目标文件。
  • ext:在dest中的所有文件后缀都替换掉。
  • flatten:在dest中的所有路径的片段都替换掉。
  • rename:每当匹配到一个src时,都会调用此方法(在ext和flatten执行之后)。dest和src属性会被当参数传入,这个函数必须返回一个新的dest值。如果相同的dest被返回超过一次,每一个用它的src都会被添加到一个源数组。

再下面这个例子中,名为 minify 的任务static_mapping和 dynamic_mapping 执行的完全相同的任务。

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.
        },
      ],
    },
  },
});


任何静态和动态的方式都可以结合使用。


2.12 模板

通过 <% %> 来定义模板,任务执行时会自动把从配置中读取数据并拓展掉模板。模板会被递归拓展,直到没有任何模板为止。

整个config对象就是使用模板的上下文。并且,Grunt 和 它的方法都可以在模板中使用,比如 <% grunt.template.today("yyy-mm-dd") %>。

  • <%= xx %> 以config对象为上下文解析出 xx 的值,类型无关。字符串、数组或者对象都可。
  • <% %> 执行任意的js代码,可以用来进行流程控制或者执行循环等。

下面这个例子是一个concat任务,执行 grunt concat:sample 会把所有符合 foo/*.js+bar/*.js+baz/*.js的文件连接起来,再加上 /* abcde */ 的baner,最后生成 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'
    },
  },
  // Arbitrary properties used in task configuration templates.
  foo: 'c',
  bar: 'b<%= foo %>d', // 'bcd'
  baz: 'a<%= bar %>e', // 'abcde'
  qux: ['foo/*.js', 'bar/*.js'],
});



2.13 导入外部数据

在下面这个例子中,项目的元数据是通过 package.json 文件导入的。uglify(http://github.com/gruntjs/grunt-contrib-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'
    }
  }
});


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值