Why use a task runner?
In one word: automation. The less work you have to do when performing repetitive tasks like minification, compilation, unit testing, linting, etc, the easier your job becomes. After you've configured it through a Gruntfile, a task runner can do most of that mundane work for you—and your team—with basically zero effort.
Getting started
Grunt and Grunt plugins are installed and managed via npm, the Node.js package manager.
Installing the CLI
In order to get started, you'll want to install Grunt's command line interface (CLI) globally.
Working with an existing Grunt project
Change to the project's root directory.
Install project dependencies with npm install.
Run Grunt with grunt.
Preparing a new Grunt project
A typical setup will involve adding two files to your project: package.json and the Gruntfile.js
package.json
This file is used by npm to store metadata for projects published as npm modules. You will list grunt and the Grunt plugins your project needs as devDependencies in this file.
Gruntfile.js
This file is used to configure or define tasks and load Grunt plugins.
The Gruntfile
A Gruntfile is comprised of the following parts:
- The "wrapper" function
- Project and task configuration
- Loading Grunt plugins and tasks
- Custom tasks
The "wrapper" function
Every Gruntfile (and gruntplugin) uses this basic format, and all of your Grunt code must be specified inside this function:
Project and task configuration
Most Grunt tasks rely on configuration data defined in an object passed to the grunt.initConfig method.
Loading Grunt plugins and tasks
Many commonly used tasks like concatenation, minification and linting are available as grunt plugins. As long as a plugin is specified in package.json as a dependency, and has been installed via npm install, it may be enabled inside your Gruntfile with a simple command.
Custom tasks
You can configure Grunt to run one or more tasks by default by defining a default task.
Grunt Configuration
Task configuration is specified in your Gruntfile via the grunt.initConfig method. This configuration will mostly be under task-named properties, but may contain any arbitrary data. As long as properties don't conflict with properties your tasks require, they will be otherwise ignored.
Also, because this is JavaScript, you're not limited to JSON; you may use any valid JavaScript here. You may even programmatically generate the configuration if necessary.
Task Configuration and Targets
When a task is run, Grunt looks for its configuration under a property of the same name. Multi-tasks can have multiple configurations, defined using arbitrarily named "targets." In the example below, the concat task has foo and bar targets, while the uglify task only has a bar target.
Options
Inside a task configuration, an options property may be specified to override built-in defaults. In addition, each target may have an options property which is specific to that target. Target-level options will override task-level options.
The options object is optional and may be omitted if not needed.
Files
Because most tasks perform file operations, Grunt has powerful abstractions for declaring on which files the task should operate. There are several ways to define src-dest (source-destination) file mappings, offering varying degrees of verbosity and control. Any multi task will understand all the following formats, so choose whichever format best meets your needs.
Compact Format
A single src-dest (source-destination) file mapping per-target.
It is most commonly used for read-only tasks, like grunt-contrib-jshint, where a single src property is needed, and no dest key is relevant. This format also supports additional properties per src-dest file mapping.
File Object Format
A multiple src-dest file mapping per-target.
This form supports multiple src-dest mappings per-target, where the property name is the destination file, and its value is the source file(s). Any number of src-dest file mappings may be specified in this way, but additional properties may not be specified per mapping.
File Array Format
Supports multiple src-dest file mappings per-target, while also allowing additional properties per mapping.
Templates
Templates specified using <% %> delimiters will be automatically expanded when tasks read them from the config. Templates are expanded recursively until no more remain.
Importing External Data
In the following Gruntfile, project metadata is imported into the Grunt config from a package.json file, and the grunt-contrib-uglify plugin uglify task is configured to minify a source file and generate a banner comment dynamically using that metadata.
Grunt has grunt.file.readJSON and grunt.file.readYAML methods for importing JSON and YAML data.
Creating tasks
Tasks are grunt's bread and butter.
Alias Tasks
If a task list is specified, the new task will be an alias for one or more other tasks. Whenever this "alias task" is run, every specified tasks in taskList will be run, in the order specified. The taskList argument must be an array of tasks.
This example alias task defines a "default" task whereby the "jshint", "qunit", "concat" and "uglify" tasks are run automatically if Grunt is executed without specifying any tasks:
Task arguments can be specified as well. In this example, the alias "dist" runs both the "concat" and "uglify" tasks, each with a "dist" argument:
Multi Tasks
When a multi task is run, Grunt looks for a property of the same name in the Grunt configuration. Multi-tasks can have multiple configurations, defined using arbitrarily named "targets."
Given the specified configuration, this example multi task would log foo: 1,2,3 if Grunt was run via grunt log:foo, or it would log bar: hello world if Grunt was run via grunt log:bar. If Grunt was run as grunt log however, it would log foo: 1,2,3 then bar: hello world then baz: false.
"Basic" Tasks
When a basic task is run, Grunt doesn't look at the configuration or environment—it just runs the specified task function, passing any specified colon-separated arguments in as function arguments.
This example task logs foo, testing 123 if Grunt is run via grunt foo:testing:123. If the task is run without arguments as grunt foo the task logs foo, no args.Custom tasks
Inside a task, you can run other tasks.