Grunt - 快速指南



Grunt - 概述

什么是 Grunt?

Grunt 是一个 JavaScript 任务运行器,可以用作 JavaScript 对象的命令行工具。它是一个构建在 NodeJS 之上的任务管理器。

为什么要使用 Grunt?

  • Grunt 可以非常轻松地执行重复性任务,例如编译、单元测试、压缩文件、运行测试等。

  • Grunt 包含内置任务,可以扩展插件和脚本的功能。

  • Grunt 的生态系统非常庞大;您可以用很少的精力自动化任何操作。

历史

GruntJS 的第一行源代码于 2011 年添加。Grunt v0.4 于 2013 年 2 月 18 日发布。Grunt v0.4.5 于 2014 年 5 月 12 日发布。Grunt 的稳定版本是 1.0.0 rc1,于 2016 年 2 月 11 日发布。

优点

  • 使用 Grunt,您可以轻松地执行文件的压缩、编译和测试。

  • Grunt 统一了 Web 开发人员的工作流程。

  • 您可以使用 Grunt 轻松地处理新的代码库,因为它包含较少的基础设施。

  • 它可以加快开发工作流程并提高项目的性能。

缺点

  • 每当 npm 包更新时,您都需要等待 Grunt 的作者更新它。

  • 每个任务都设计用于执行指定的工作。如果要扩展指定的任务,则需要使用一些技巧才能完成工作。

  • Grunt 包含大量用于各个插件的配置参数。通常,Grunt 配置文件较长。

Grunt - 特性

Grunt 是一个基于 JavaScript 的任务运行器,这意味着它可以自动化工作流程中的重复性任务,并且可以用作 JavaScript 对象的命令行工具。

GruntJS 的一些最突出的特性如下所示:

  • Grunt 使工作流程像编写设置文件一样简单。

  • 您可以用最少的精力自动化重复性任务。

  • Grunt 是一个基于 NodeJS 的流行任务运行器。它灵活且被广泛采用。

  • 它采用了一种直接的方法,包括 JS 中的任务和 JSON 中的配置。

  • Grunt 压缩 JavaScript、CSS 文件、测试文件、编译 CSS 预处理器文件(SASS、LESS)等。

  • Grunt 包含内置任务,可以扩展插件和脚本的功能。

  • 它可以加快开发工作流程并提高项目的性能。

  • 您可以使用 Grunt 轻松地处理新的代码库,因为它包含较少的基础设施。

  • Grunt 的生态系统非常庞大;您可以用很少的精力自动化任何操作。

  • Grunt 减少了在执行重复性任务时出错的可能性。

  • Grunt 目前拥有超过 4000 个插件。

  • 它可以用于大型生产站点。

Grunt - 安装

本章提供了如何在系统上安装 Grunt 的分步过程。

Grunt 的系统要求

  • 操作系统 - 跨平台

  • 浏览器支持 - IE(Internet Explorer 8+)、Firefox、Google Chrome、Safari、Opera

Grunt 的安装

步骤 1 - 我们需要 NodeJs 来运行 Grunt。要下载 NodeJs,请打开链接 https://node.org.cn/en/,您将看到如下所示的屏幕:

Grunt Installation

下载压缩文件的最新功能版本。

步骤 2 - 接下来,运行安装程序以在您的计算机上安装NodeJs

步骤 3 - 接下来,您需要设置环境变量

路径用户变量

  • 右键单击我的电脑
  • 选择属性
  • 接下来,选择高级选项卡,然后单击环境变量
Grunt Installation
  • 环境变量窗口下,双击PATH,如屏幕所示。

Grunt Installation
  • 您将获得一个编辑用户变量窗口,如所示。在变量值字段中添加 NodeJs 文件夹路径,如C:\Program Files\nodejs\node_modules\npm。如果已为其他文件设置了路径,则需要在其后添加分号(;),然后添加 NodeJs 路径,如下所示:

Grunt Installation

最后,单击确定按钮。

系统变量

  • 系统变量下,双击Path,如以下屏幕所示。

Grunt Installation
  • 您将获得一个编辑系统变量窗口,如所示。在变量值字段中添加 NodeJs 文件夹路径,如C:\Program Files\nodejs\,然后单击确定,如下所示:

Grunt Installation

步骤 4 - 要在您的系统上安装 grunt,您需要全局安装 Grunt 的命令行界面 (CLI),如下所示:

npm install -g grunt-cli

运行上述命令会将grunt命令放入您的系统路径中,这使其能够从任何目录运行。

安装grunt-cli不会安装 Grunt 任务运行器。grunt-cli的作用是运行已安装在Gruntfile旁边的 Grunt 版本。它允许一台机器同时安装多个版本的 Grunt。

步骤 5 - 现在,我们将创建配置文件以运行 Grunt。

package.json

package.json文件放置在项目的根目录中,位于Gruntfile旁边。package.json用于在您在与 package.json 相同的文件夹中运行命令npm install时正确运行每个列出的依赖项。

可以通过在命令提示符中键入以下命令来创建基本的package.json

npm init

基本的package.json文件将如下所示:

{
   "name": "tutorialspoint",
   "version": "0.1.0",
   "devDependencies": {
      "grunt-contrib-jshint": "~0.10.0",
      "grunt-contrib-nodeunit": "~0.4.1",
      "grunt-contrib-uglify": "~0.5.0"
   }
}

您可以通过以下命令将 Grunt 和 gruntplugins 添加到现有的pacakge.json文件中:

npm install <module> --save-dev

在上述命令中,<module>表示要本地安装的模块。上述命令还会自动将<module>添加到devDependencies中。

例如,以下命令将安装最新版本的Grunt并将其添加到您的devDependencies中:

npm install grunt --save-dev

Gruntfile.js

Gruntfile.js文件用于定义我们 Grunt 的配置。这是我们编写设置的地方。基本的Gruntfile.js文件如下所示:

// our wrapper function (required by grunt and its plugins)
// all configuration goes inside this function
module.exports = function(grunt) {
   // CONFIGURE GRUNT
   grunt.initConfig({
      // get the configuration info from package.json file
      // this way we can use things like name and version (pkg.name)
      pkg: grunt.file.readJSON('package.json'),

      // all of our configuration goes here
      uglify: {
         // uglify task configuration
         options: {},
         build: {}
      }
   });

   // log something
   grunt.log.write('Hello world! Welcome to Tutorialspoint!!\n');

   // Load the plugin that provides the "uglify" task.
   grunt.loadNpmTasks('grunt-contrib-uglify');

   // Default task(s).
   grunt.registerTask('default', ['uglify']);
};

Grunt - 入门

要使用 Grunt,您需要安装 Node.js。Node.js 的安装已在前面的章节中进行了说明。您可以使用 Node.js 包管理器安装 Grunt 和 Grunt 插件。

在系统上设置 Grunt 之前,您可以使用以下命令更新 Node 包管理器:

npm update -g npm

如果您使用的是 Mac 或 Linux,则需要在命令行的开头使用sudo字样以授予管理员访问权限,如下所示:

sudo npm update -g npm

CLI 安装

CLI 代表命令行界面,它运行已安装的 Grunt 版本。要开始使用 Grunt,您需要全局安装 Grunt 的命令行界面 (CLI),如下所示:

npm install -g grunt-cli

运行上述命令会将 grunt 命令放入您的系统路径中,这使其能够从任何目录运行。您无法通过安装grunt-cli来安装 Grunt 任务运行器。它允许一台机器同时安装多个版本的 Grunt。

CLI 的工作原理

每当运行 Grunt 时,CLI 会使用require()系统在您的系统上查找已安装的 Grunt。使用grunt-cli,您可以从项目中的任何目录运行 Grunt。如果您使用的是本地安装的 Grunt,则 grunt-cli 使用本地安装的 Grunt 库并应用来自 Grunt 文件的配置。

处理现有项目和新项目

如果您正在处理一个已配置的项目,其中包含package.jsonGruntfile,则请按照以下说明进行操作:

  • 找到项目根目录的路径。
  • 您可以使用npm install命令安装依赖项。
  • 使用grunt命令运行 Grunt。

如果您正在创建一个新项目,则将两个文件package.jsonGruntfile包含到您的项目中。

  • package.json - package.json文件放置在项目的根目录中,并且在您在同一文件夹中运行命令npm install时用于运行每个列出的依赖项。

  • Gruntfile.js - Gruntfile.js文件用于编写项目的配置设置。

package.json

package.json文件放置在项目的根目录中,位于Gruntfile旁边,并且在您在同一文件夹中运行命令npm install时用于运行每个列出的依赖项。

您可以通过以下列出的不同方式创建package.json

  • 您可以使用grunt-init创建 package.json 文件。
  • 您也可以使用npm-init命令创建 package.json 文件。

您可以编写如下所示的规范:

{
   "name": "tutorialspoint",
   "version": "0.1.0",
   "devDependencies": {
      "grunt-contrib-jshint": "~0.10.0",
      "grunt-contrib-nodeunit": "~0.4.1",
      "grunt-contrib-uglify": "~0.5.0"
   }
}

您可以通过使用以下命令将 Grunt 和 gruntplugins 添加到现有的 pacakge.json 文件中:

npm install <module> --save-dev

这里,<module>表示要本地安装的模块。上述命令将安装指定的模块并自动将其添加到devDependencies部分。

例如,以下命令将安装最新版本的Grunt并将其添加到您的devDependencies中:

npm install grunt --save-dev

Gruntfile

Gruntfile.js文件是默认位置,您将在其中为 Grunt 添加配置设置。Grunt 文件包含以下部分:

  • 包装函数
  • 项目和任务配置
  • 加载 Grunt 插件和任务
  • 自定义任务

基本的Gruntfile.js文件如下所示:

// our wrapper function (required by grunt and its plugins)
// all configuration goes inside this function
module.exports = function(grunt) {

   // CONFIGURE GRUNT
   grunt.initConfig({
      // get the configuration info from package.json file
      // this way we can use things like name and version (pkg.name)
      pkg: grunt.file.readJSON('package.json'),

      // all of our configuration goes here

   });

   // Load the plugin that provides the "uglify" task
   grunt.loadNpmTasks('grunt-contrib-uglify');

   // Default task(s)
   grunt.registerTask('default', ['uglify']);
};

包装函数

在上面的代码中,module.exports是一个包装函数,整个配置都位于此函数内部。这是一种将配置显示给应用程序其余部分的方式。

module.exports = function(grunt) {
   //do grunt-related things here
}

项目和任务配置

准备好 Grunt 配置后,您可以配置 Grunt 任务。项目配置可以写入grunt.initConfig()部分。在grunt.initConfig()函数内部,从 package.json 文件中获取配置信息并将其保存到pkg中。您可以使用pkg.name调用项目名称,使用pkg.version调用版本。

加载 Grunt 插件和任务

使用grunt.loadNpmTasks方法从指定的插件加载任务。您可以使用npm本地安装插件,并且它必须相对于 Gruntfile。您可以使用简单的命令加载插件,如下所示:

grunt.task.loadNpmTasks(pluginName)

自定义任务

当您通过命令行运行 Grunt 时,Grunt 将查找default任务。在上面的代码中,我们使用了一个名为uglify的任务,它可以使用grunt命令运行。这与显式运行grunt uglify命令相同,您可以在数组中指定任务数量。

grunt.registerTask('default', ['uglify']);

Grunt - 配置任务

您可以在Gruntfile.js 文件中定义项目特定的配置数据。

Grunt 配置

可以通过使用grunt.initConfig()方法在 Gruntfile 中初始化任务配置数据。在grunt.initConfig()函数内部,获取来自 package.json 文件的配置信息。配置将包含一个名为properties的任务和任意数据。

grunt.initConfig({
   jshint: {
      // configuration for jshint task
   },
   cssmin: {
      // configuration for cssmin task
   },
   // Arbitrary non-task-specific properties
   my_files: ['dir1/*.js', 'dir2/*.js'],
});

任务配置和目标

当您运行任务时,Grunt 会在以任务命名的属性下查找配置。我们将定义具有多个配置和目标选项的任务,如下所示:

grunt.initConfig({
   jshint: {
      myfile1: {
         // configuration for "myfile1" target options
      },
      myfile2: {
         // configuration for "myfile2" target options
      },
   },
   cssmin: {
      myfile3: {
         // configuration for "myfile3" target options
      },
   },
});

这里,jshint 任务具有 myfile1myfile2 目标,而 cssmin 任务具有 myfile3 目标。当您运行 grunt jshint 时,它将遍历任务和目标以处理指定目标的配置。

选项

在任务配置内定义 options 属性,该属性会覆盖任务默认值。每个目标都包含 options 属性,该属性会覆盖任务级别的选项。它将具有以下格式:

grunt.initConfig({
   jshint: {
      options: {
         // task-level options that overrides task defaults
      },
      myfile: {
         options: {
            // "myfile" target options overrides task defaults
         },
      },

      myfile1: {
         // there is no option, target will use task-level options
      },
   },
});

文件

Grunt 提供了一些关于指定任务应操作哪些文件的思路,并使用不同的方法来指定 src-dest 文件映射。以下是 srcdest 映射支持的一些其他属性:

  • filter - 它是一个函数,用于指定匹配的 src 文件路径并返回 true 或 false 值。

  • nonull - 当设置为 true 时,它定义不匹配的模式。

  • dot - 它匹配以句点开头的文件名或其他文件名。

  • matchBase - 它匹配包含斜杠且与路径基本名称匹配的模式。

  • expand - 它处理 src-dest 文件映射。

紧凑格式

它指定每个目标的 src-dest 文件映射,可用于只读任务,并且只需要 src 属性,不需要 dest 属性。

grunt.initConfig({
   jshint: {
      myfile1: {
         src: ['src/file1.js','src/file2.js']
      },
   },
   cssmin: {
      myfile2: {
         src: ['src/file3.js','src/file4.js'],
         dest: 'dest/destfile.js',
      },
   },
});

文件对象格式

它指定每个目标的 src-dest 文件映射,其中属性名称为 dest 文件,其值为 src 文件。

grunt.initConfig({
   jshint: {
      myfile1: {
         files: {
            'dest/destfile.js':['src/file1.js','src/file2.js'],
            'dest/destfile1.js':['src/file3.js','src/file4.js'],
         },
      },
      myfile2: {
         files: {
            'dest/destfile2.js':['src/file22.js','src/file23.js'],
            'dest/destfile21.js':['src/file24.js','src/file25.js'],
         },
      },
   },
});

文件数组格式

它通过使用每个映射的其他属性来指定每个目标的 src-dest 文件映射。

grunt.initConfig({
   jshint: {
      myfile1: {
         files: [
            {src:['src/file1.js','src/file2.js'],dest:'dest/file3.js'},
            {src:['src/file4.js','src/file4.js'],dest:'dest/file5.js'},
         ],
      },
      myfile2: {
         files: [
            {src:['src/file6.js','src/file7.js'],dest:'dest/file8/', nonull:true},
            {src:['src/file9.js','src/file10.js'],dest:'dest/file11/', filter:'isFalse'},
         ],
      },
   },
});

旧格式

dest-as-target 文件格式在多任务存在之前就存在了,其中目标文件路径是目标的名称。以下格式已弃用,代码中不应使用。

grunt.initConfig({
   jshint: {
      'dest/destfile2.js':['src/file3.js','src/file4.js'],
      'dest/destfile5.js':['src/file6.js','src/file7.js'],
   },
});

自定义过滤器函数

您可以通过使用 filter 属性,更详细地帮助目标文件。以下格式仅在匹配实际文件时才清理文件。

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

通配符模式

通配符表示扩展文件名。Grunt 通过使用 内置的 node-globminimatch 库 支持通配符。通配符模式包括以下几点:

  • * 匹配任意数量的字符,但不匹配 /
  • ? 匹配单个字符,但不匹配 /
  • ** 匹配任意数量的字符,包括 /
  • {} 指定以逗号分隔的“或”表达式列表。
  • ! 将在开头否定模式匹配。

例如:

{src: 'myfile/file1.js', dest: ...} // it specifies the single file

{src: 'myfile/*.js', dest: ...} //it matches all the files ending wth .js

{src: 'myfile/{file1,file2}*.js', dest: ...} //defines the single node glob pattern

{src: ['myfile/*.js', '!myfile/file1.js'], dest: ...} // all files will display in alpha

// order except for file1.js

动态构建文件对象

当您处理单个文件时,可以使用其他属性来动态构建文件列表。当您将 expand 属性设置为 true 时,它将启用以下一些属性:

  • cwd 将所有 src 匹配到此路径。

  • src 匹配要匹配的模式,相对于 cwd

  • dest 属性指定目标路径前缀。

  • ext 将用在 dest 路径中生成的 value 替换现有扩展名。

  • extDot 指示指示扩展名的句点所在位置。它使用第一个句点或最后一个句点;默认情况下,它设置为第一个句点。

  • flattendest 路径中删除所有路径部分。

  • rename 指定包含新目标和文件名的字符串。

Rename 属性

它是一个唯一的 JavaScript 函数,返回一个字符串,您不能对 rename 使用字符串值。在以下示例中,copy 任务将创建 README.md 的备份。

grunt.initConfig({
   copy: {
      backup: {
         files: [{
            expand: true,
            src: ['docs/README.md'],    // creating a backup of README.md
            rename: function () {       // specifies the rename function
               return 'docs/BACKUP.txt'; // returns a string with the complete destination
            }
         }]
      }
   }
});

模板

您可以使用 <% %> 分隔符指定模板。读取配置时,它们将自动扩展。它包括两种类型的属性:

  • <%= prop.subprop %> 属性用于扩展配置中prop.subprop 的值,可以引用字符串值、数组和其他对象。

  • <% %> 属性执行用于控制流或循环的内联 JavaScript 代码。

例如:

grunt.initConfig({
   concat: {
      myfile: {
         options: {
            banner: '/* <%= val %> */\n',
         },
         src: ['<%= myval %>', 'file3/*.js'],
         dest: 'build/<%= file3 %>.js',
      },
   },
   // properties used in task configuration templates
   file1: 'c',
   file2: 'b<%= file1 %>d',
   file3: 'a<%= file2 %>e',
   myval: ['file1/*.js', 'file2/*.js'],
});

导入外部数据

您可以从 package.json 文件 导入外部数据。grunt-contrib-uglify 插件可用于缩小源文件,并使用元数据创建横幅注释。您可以使用 grunt.file.readJSONgrunt.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'
      }
   }
});

Grunt - 示例文件

在本章中,让我们使用以下插件创建一个简单的 Grunt 文件:

  • grunt-contrib-uglify
  • grunt-contrib-concat
  • grunt-contrib-jshint
  • grunt-contrib-watch

安装所有上述插件,并按照以下步骤创建一个简单的 Gruntfile.js

步骤 1 - 您需要创建一个 wrapper 函数,该函数封装 Grunt 的配置。

module.exports = function(grunt) {};

步骤 2 - 初始化您的配置对象,如下所示:

grunt.initConfig({});

步骤 3 - 接下来,将项目设置从 package.json 文件读取到 pkg 属性中。它使我们能够在您的 package.json 文件中引用属性值。

pkg: grunt.file.readJSON('package.json')

步骤 4 - 接下来,您可以为任务定义配置。让我们创建我们的第一个任务 concat 来连接 src/ 文件夹中存在的所有文件,并将连接的 .js 文件存储在 dist/ 文件夹下。

concat: {
   options: {
      // define a string to insert between files in the concatenated output
      separator: ';'
   },
   dist: {
      // files needs to be concatenated
      src: ['src/**/*.js'],
      // location of the concatenated output JS file
      dest: 'dist/<%= pkg.name %>.js'
   }
}

步骤 5 - 现在,让我们创建另一个名为 uglify 的任务来缩小我们的 JavaScript。

uglify: {
   options: {
      // banner will be inserted at the top of the output which displays the date and time
      banner: '/*! <%= pkg.name %> <%= grunt.template.today() %> */\n'
   },
   dist: {
      files: {
         'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
      }
   }
}

上述任务在 dist/ 文件夹内创建一个文件,其中包含缩小的 .js 文件。<%= concat.dist.dest %> 将指示 uglify 缩小 concat 任务生成的的文件。

步骤 6 - 让我们通过创建 jshint 任务来配置 JSHint 插件。

jshint: {
   // define the files to lint
   files: ['Gruntfile.js', 'src/**/*.js'],
   // configure JSHint
   options: {
      // more options here if you want to override JSHint defaults
      globals: {
         jQuery: true,
      }
   }
}

上述 jshint 任务接受一个文件数组,然后是一个选项对象。上述任务将在 Gruntfile.jssrc/**/*.js 文件中查找任何编码违规。

步骤 7 - 接下来,我们有 watch 任务,它查找任何指定文件的更改并运行您指定的任务。

watch: {
   files: ['<%= jshint.files %>'],
   tasks: ['jshint']
}

步骤 8 - 接下来,我们必须加载已通过 _npm 安装的所有 Grunt 插件。

grunt.loadNpmTasks('grunt-contrib-uglify');

grunt.loadNpmTasks('grunt-contrib-jshint');

grunt.loadNpmTasks('grunt-contrib-watch');

grunt.loadNpmTasks('grunt-contrib-concat');

步骤 9 - 最后,我们必须定义 default 任务。

grunt.registerTask('default', ['jshint', 'concat', 'uglify']);

只需在命令行上键入 grunt 命令即可运行 default 任务。

这是您完整的 Gruntfile.js

module.exports = function(grunt) {

   grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),
      concat: {
         options: {
            separator: ';'
         },
         dist: {
            src: ['src/**/*.js'],
            dest: 'dist/<%= pkg.name %>.js'
         }
      },
      uglify: {
         options: {
            banner: '/*! <%= pkg.name %> <%= grunt.template.today() %> */\n'
         },
         dist: {
            files: {
               'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
            }
         }
      },
      jshint: {
         // define the files to lint
         files: ['Gruntfile.js', 'src/**/*.js'],
         // configure JSHint
         options: {
            // more options here if you want to override JSHint defaults
            globals: {
               jQuery: true,
            }
         }
      },
      watch: {
         files: ['<%= jshint.files %>'],
         tasks: ['jshint']
      }
   });

   grunt.loadNpmTasks('grunt-contrib-uglify');
   grunt.loadNpmTasks('grunt-contrib-jshint');
   grunt.loadNpmTasks('grunt-contrib-watch');
   grunt.loadNpmTasks('grunt-contrib-concat');

   grunt.registerTask('default', ['jshint', 'concat', 'uglify']);

};

Grunt - 创建任务

在本章中,让我们学习 创建任务。每当您运行 Grunt 时,都会指定一个或多个要运行的任务,通知 Grunt 您希望它执行的操作。如果您指定了 default 任务,则它将默认运行。

别名任务

每当指定任务列表时,一个或多个其他任务都可以通过新任务进行别名化。运行别名将依次运行 taskList 中指定的每个任务。taskList 参数应为任务数组,如下所示:

grunt.registerTask(taskName, [description, ] taskList)	

例如,当您使用 jshintconcatuglify 任务定义 taskList 并将 taskName 指定为 default 时,如果 Grunt 在未指定任何任务的情况下执行,则所有列出的任务都将自动运行。

grunt.registerTask('default', ['jshint', 'concat', 'uglify']);

您还可以指定任务参数,如下所示:

grunt.registerTask('dist', ['concat:dist', 'uglify:dist']);	

在上述任务中,别名 dist 运行 concatuglify 任务。

多任务

每当您运行多个任务时,Grunt 都会在 Grunt 配置中搜索同名属性。这些任务可以有多个配置,这些配置将使用任意命名的 targets 定义。

当您同时指定任务和目标时,只会处理指定的 target 配置。

grunt concat:foo

上述命令将只运行目标 foo

当您只指定任务时,将处理所有目标。

grunt concat

上述命令将遍历 concat 任务的所有目标。

当您使用 grunt.task.renameTask 重命名任务时,Grunt 会在 config 对象中搜索具有 new 任务名称的属性。

grunt.initConfig({
   log: {
      foo: [1, 2, 3],
      bar: 'Welcome to tutorialspoint',
      sap: true
   }
});

grunt.registerMultiTask('log', 'Log stuff.', function() {
   grunt.log.writeln(this.target + ': ' + this.data);
});

在上面的示例中,如果 Grunt 通过 grunt log:foo 运行,则多任务将记录 foo: 1,2,3;如果通过 grunt log:bar 运行,则将记录 bar: Welcome to tutorialspoint。当 Grunt 作为 grunt log 运行时,它将首先记录 foo: 1,2,3,然后记录 bar: Welcome to tutorialspoint,最后记录 sap: true

基本任务

每当您运行基本任务时,Grunt 不会搜索配置或环境。而是运行指定的 task 函数,并将作为函数参数指定的任何冒号分隔的参数传递进去。

grunt.registerTask(taskName, [description, ] taskFunction)	

在以下示例中,如果 Grunt 通过 grunt foo:testing:123 命令执行,则任务将记录 foo, testing 123。每当任务在没有参数的情况下作为 grunt foo 运行时,任务将 log foo, no args

grunt.registerTask('foo', 'A simple task to logs stuff.', function(arg1, arg2) {
   if (arguments.length === 0) {
      grunt.log.writeln(this.name + ", no args");
   } else {
      grunt.log.writeln(this.name + ", " + arg1 + " " + arg2);
   }
});

自定义任务

如果您不想遵循 多任务 结构,您可以定义自定义任务,如下所示:

grunt.registerTask('default', 'My "default" task description.', function() {
  grunt.log.writeln('Currently running the "default" task.');
});  

可以在另一个任务中运行任务,如下所示:

grunt.registerTask('foo', 'My "foo" task.', function() {
   // Enqueue bar and baz tasks, to run after foo completes, in-order.
   grunt.task.run('bar', 'baz');
   // Or:
   grunt.task.run(['bar', 'baz']);
});  

您还可以创建异步任务,如下所示:

grunt.registerTask('asyncfoo', 'My "asyncfoo" task.', function() {
   // Force task into async mode and grab a handle to the done() function.
   var done = this.async();
   // Run some sync stuff.
   grunt.log.writeln('Processing your task..');
   // Run some async stuff.
   setTimeout(function() {
      grunt.log.writeln('Finished!');
      done();
   }, 1000);
});

您可以创建可以访问其名称和参数的任务,如下所示:

grunt.registerTask('foo', 'My task "foo" .', function(a, b) {
   grunt.log.writeln(this.name, a, b);
});

// Usage:
// grunt foo
//   logs: "foo", undefined, undefined
// grunt foo:bar
//   logs: "foo", "bar", undefined
// grunt foo:bar:baz
//   logs: "foo", "bar", "baz"

您可以创建任务,以便每当记录任何错误时,任务都可能失败,如下所示:

grunt.registerTask('foo', 'My task "foo" .', function() {
   if (failureOfSomeKind) {
      grunt.log.error('This is an error message.');
   }

   // If this task had errors then fail by returning false
   if (ifErrors) { return false; }

   grunt.log.writeln('This is success message');
});  

每当任务失败时,所有后续任务都将终止,除非指定了 --force

grunt.registerTask('foo', 'My task "foo" .', function() {
   // Fail synchronously.
   return false;
});

grunt.registerTask('bar', 'My task "bar" .', function() {
   var done = this.async();
   setTimeout(function() {
      // Fail asynchronously.
      done(false);
   }, 1000);
});  

任务可能依赖于其他任务才能成功执行。请记住,grunt.task.requires 实际上不会执行其他任务,而只是检查它是否已执行且未失败。

grunt.registerTask('foo', 'My task "foo" .', function() {
   return false;
});

grunt.registerTask('bar', 'My task "bar" .', function() {
   // Fail task if foo task failed or never ran.
   grunt.task.requires('foo');
   // This code executes if the foo task executed successfully.
   grunt.log.writeln('Hello, World.. Welcome to Tutorialspoint!..');
});

// Usage:
// grunt foo bar doesn't log, because foo failed to execute.
// **Note: This is an example of space-separated sequential commands,
// (similar to executing two lines of code: `grunt foo` then `grunt bar`)
// grunt bar doesn't log, because foo never ran.  

如果找不到所需的配置属性,任务甚至可能失败。

grunt.registerTask('foo', 'My task "foo" .', function() {
   // Fail task if meta.name config properties is missing
   // Format 1: String 
   grunt.config.requires('meta.name');
   // or Format 2: Array
   grunt.config.requires(['meta', 'name']);
   // Log... conditionally.
   grunt.log.writeln('This only log if meta.name is defined in the config.');
});  

任务可以访问配置属性,如下所示:

grunt.registerTask('foo', 'My task "foo" .', function() {
   // Log the value of the property. Returns null if the property is undefined.
   grunt.log.writeln('The meta.name property is: ' + grunt.config('meta.name'));
   // Also logs the value of the property. Returns null if the property is undefined.
   grunt.log.writeln('The meta.name property is: ' + grunt.config(['meta', 'name']));
});  
广告