Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Grunt configuration tasks


May 25, 2021 Grunt


Table of contents


Configure the task

This guide explains how to use Gruntfile to configure task for your project. If you don't yet know what Gruntfile is, read the Quick Start guide and take a look at this Gruntfile example.

Grunt configuration

Grunt's task configuration is specified in the Gruntfile grunt.initConfig method. T his configuration is primarily a property named after a task name and can also contain any other data. Once these properties representing arbitrary data conflict with the properties required by the task, they are ignored.

In addition, since this is JavaScript in itself, you are not limited to using JSON; If necessary, you can even build configurations programmatically.

grunt.initConfig({
  concat: {
    // 这里是concat任务的配置信息。
  },
  uglify: {
    // 这里是uglify任务的配置信息
  },
  // 任意数据。
  my_property: 'whatever',
  my_src_files: ['foo/*.js', 'bar/*.js'],
});

Task configuration and target

When a task is run, Grunt automatically looks for properties with the same name in the configuration object. M ultitas missions can define multiple configurations by any named target. In the following case, the concat task has two targets called foo and bar, while the uglify task has only one target called 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.
    },
  },
});

Specifying both tasks and targets, such as grunt concat:foo or grunt concat:bar, will only handle the configuration of the specified target, while running grunt concat will traverse all targets and process them in turn. Note that if a task has been renamed with grunt.task.renameTask, Grunt will look for properties named after the new task name in the configuration object.

Options properties

In a task configuration, options properties can be used to specify default values that override built-in properties. I n addition, each target can have an options property specific to that target. Target-level flat options will override task-level options.

Options objects are optional and can be ignored if not needed.

grunt.initConfig({
  concat: {
    options: {
      // 这里是任务级的Options,覆盖默认值 
    },
    foo: {
      options: {
        // "foo" target options may go here, overriding task-level options.
      },
    },
    bar: {
      // No options specified; this target will use task-level options.
    },
  },
});

File

Since most tasks are file operations, Grunt has a powerful abstraction layer to declare which files the task should manipulate. T here are several ways to define src-dest (source-target file) file mapping, all of which provide varying degrees of description and control of how to operate. Any multitaser can understand the following format, so you just need to choose the format that meets your needs.

All file formats support src and dest properties, in addition to the Compact and Files Array formats, which also support some of the following additional properties:

  • Filter it by accepting any one of the valid fs. The Stats method name or a function matches the src file path and returns true or false based on the matching results.
  • If nonull is set to true, unmatched patterns are also executed. Combined with Grunt's --verbore flag, this option can help debug problems with file paths.
  • dot It allows the pattern pattern to match the file name at the beginning of the period, even if the pattern does not specify whether there is a period at the beginning of the file name.
  • If matchBase sets this property, the missing slash pattern (meaning that slashes cannot be used in the pattern to match file paths) will not match the file names contained in the slashes. For example, a?b will match/xyz/123/acb but not /xyz/acb/123.
  • Expand handles dynamic src-dest file mapping, see Dynamic Build File Object for more information.
  • Other properties are passed as matches to the underlying library. Check out the node-glob and minimatch documentation for more information.

Simple format

This form allows one src-dest file map for each target. T ypically it is used for read-only tasks such as grunt-contrib-jshint, which require only a single src property and does not require the associated list option. This format also specifies additional properties for each src-dest file map.

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

The file object format

This form supports file mapping in the form of multiple src-dests for each target, with the property name the target file and the source file as its value (the list of source files is declared in array format). You can specify several src-dest file maps in this way, but you cannot specify additional properties for each map.

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

The file array format

This form supports multiple src-dest file maps for each target, while also allowing each map to have additional properties:

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

Older format

The dest-as-target file format is a transition before multitasing and targeting occur, and the target file path is actually the target name. U nfortunately, because the target name is a file path, running the grunt task:target may not be appropriate. In addition, you cannot specify a target-level options or specify additional properties for each src-dest file map.

This format is no longer approved, please try not to use it.

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

Custom filtering functions

Filter properties can provide you with more advanced and detailed help information for your target file. O nly one valid fs. is required. T he name of the Stats method. The following configuration cleans up only one real file that matches the pattern:

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

Or create your own finder function to return true or false depending on whether the file matches. The following example will clean up only one empty directory:

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

Wildcard mode

It is generally impractical to specify all source file paths separately, so Grunt matches file names (also known as globbing) with built-in support for node-glob and minimatch libraries.

However, this is not a comprehensive tutorial on matching patterns, you just need to know how to use them during file path matching:

  • Match any number of characters, but don't match /
  • ? Matches a single character, but does not match /
  • Match any number of characters, including /, as long as it is the only part of the path
  • A list of "or" expressions that are split with a comma is allowed
  • ! Used at the beginning of the pattern to exclude any files matched by a matching pattern

What everyone needs to know is that foo/.js will match all files at the end of the .js in the foo/directory, and foo/s/js will match the foo/directory and all files ending in .js in its subdirect directory.

In addition, to simplify the already complex wildcard pattern, Grunt allows you to specify a file path in the form of an array or a wildcard pattern. A ll modes are processed sequentially, and patterns are processed with! T he files matched by the pattern of the prefix will not be included in the result set. And each item in the result set is unique.

For example:

// 指定单个文件:
{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: ...}

For more information on the syntax of wildcard patterns, check out the documentation for node-glob and minimatch.

Dynamically build file objects

When you want to work with a large number of individual files, here are some additional properties that you can use to dynamically build a list of files. These properties can be used in the Compact and File Array file mapping formats.

Expand is set to true to enable the following options:

  • All cwd src-specified matches will be relative to the path specified here (but not this path).
  • The matching pattern of src relative to the cwd path.
  • The dest target file path prefix.
  • Ext replaces the extension with this property value for all actual existing files in the generated test path.
  • extDot is used to specify the location of the English dot that marks the extension. You can assign 'first' (extension starts with the first English dot in the file name) or 'last' (extension starts with the last English dot), and the default value is 'first' (added to version 0.4.3)
  • Flatten removes all path parts from the generated test path.
  • rename calls this function for each matching src file (after renaming the suffix and removing the path). D est and the matching src path are passed in as arguments, and this function should return a new dest value. If the same test is returned more than once, each src source that returns this value is added to an array as the source list.

In the following example, the static_mappings and dynamic_mappings targets in the uglify task have the same list of src-dest file maps because Grunt automatically expands them when the task runs dynamic_mappings the file object is mapped to four separate static src-dest files -- assuming that the four files can be found.

You can specify that any static src-dest and dynamic src-dest file maps are combined.

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

Template

The template specified using the .lt;% %?gt; separator automatically extends the scan when the task reads the appropriate data from their configuration. The template is recursively expanded until the remaining template-related information (matching the template) no longer exists in the configuration.

The entire configuration object determines the property context (the properties in the template). In addition, the use of grunt in templates and its methods are valid, for example: slt;%=grunt.template.today ('yyyy-mm-dd') %?gt;.

  • The value of prop.subprop in the configuration information will be automatically expanded, regardless of type. A template like this can be used not only to refer to string values, but also to arrays or other object types.
  • Perform any inline JavaScript code. This is useful for controlling a flow or loop.

Take the concat task configuration as an example, and run the grunt concat:sample to generate a file named build/abcde.js by matching all the files in the banner by foo/.js-bar/.js-bar/.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'],
});

Import external data

In The following Gruntfile, the project's metadata is imported from the package.json file into the Grunt configuration, and the uglify task in the grunt-contrib-uglify plug-in is configured to compress a source file and generate a banner comment using the metadata dynamically.

Grunt has two methods, grunt.file.readJSON and grunt.file.readYAML, which are used to introduce JSON and YAML data, respectively.

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'
    }
  }
});