Run environment-specific builds with Grunt multi-task targets
Configure Grunt multi-task targets so one task copies files to different output directories for development and production.
21 Jun 2026, 19:35 UTC

The problem: one build output for every environment
You need the same source files copied to different output folders, for example dist/dev/ for development and dist/prod/ for production, without maintaining separate Gruntfiles or editing paths by hand. The useful takeaway is to define one Grunt multi-task with named targets, then invoke the target you need from the command line: grunt copy:dev or grunt copy:prod.
How Grunt multi-task targets work
A multi-task is a Grunt task that can contain multiple named targets. Each target has its own files, options, and data. Inside a custom task function, Grunt exposes the current target through this.target, and target-specific options through this.options(). File sources use minimatch glob patterns; setting expand: true tells Grunt to expand each source file into a separate source-destination pair.
cwd sets the working directory for the glob, src lists the patterns to match, and dest is the output directory. Paths in src and cwd are relative to the Gruntfile directory unless you set cwd or use absolute paths.
Worked Gruntfile configuration
This example assumes Grunt 1.x and the grunt-contrib-copy plugin installed in the project. It defines a copy multi-task with dev and prod targets.
module.exports = function (grunt) {
grunt.initConfig({
copy: {
dev: {
files: [
{
expand: true,
cwd: 'src',
src: ['**/*.js', '**/*.css'],
dest: 'dist/dev/'
}
]
},
prod: {
files: [
{
expand: true,
cwd: 'src',
src: ['**/*.js', '**/*.css'],
dest: 'dist/prod/'
}
]
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.registerTask('default', ['copy:dev']);
};
The dev target writes matched files from src/ into dist/dev/, preserving the relative folder structure because expand: true is set. The prod target does the same into dist/prod/. The default task runs copy:dev when you execute grunt with no arguments.
Run the targets from the command line
Run these commands in the project directory that contains Gruntfile.js and node_modules/. No special permissions are required to read local source files or write to local output directories; avoid running Grunt with sudo, which can change ownership of files in node_modules/.
Install the plugin
npm install grunt grunt-contrib-copy --save-dev
This modifies package.json and package-lock.json. Expected check: node_modules/grunt-contrib-copy exists after installation.
Confirm the Grunt version
grunt --version
Expected check: the CLI and local grunt package report compatible 1.x versions.
Run each target
grunt copy:dev
grunt copy:prod
Expected checks: dist/dev/ and dist/prod/ are populated with copies of the matched src files. Run ls dist/dev and ls dist/prod to confirm.
Risks: targets are not separate CLI tasks. Running grunt prod produces an Unknown task error; the correct form is grunt copy:prod. Glob patterns are relative to the Gruntfile directory, so running Grunt from a subdirectory can match no files silently.
Common mistakes and limits
- Forgetting grunt.loadNpmTasks. Every plugin must be loaded before its task name can run. Missing this call produces an Unknown task error.
- Confusing targets with tasks. Use grunt taskname:target, not grunt target.
- Assuming live reload. Editing Gruntfile.js does not reload configuration in a running Grunt process. Restart Grunt or use grunt-contrib-watch for automation.
- Large file trees. Grunt copies files to disk rather than streaming them, so very large projects can be slower than streaming build tools.
Verify the result
- Run grunt --version to confirm the installed Grunt CLI and local package match expectations.
- Run grunt copy:dev and inspect dist/dev/.
- Run grunt copy:prod and inspect dist/prod/.
- Optionally add grunt.log.writeln('Target: ' + this.target) inside a custom task function to confirm target-specific execution during a run.
- Run grunt with no arguments to confirm the default task executes copy:dev.
Rollback
Running these tasks writes files to dist/dev/ and dist/prod/. To undo the operation, delete the generated output directories, for example rm -rf dist/dev dist/prod, or revert them through version control if they are tracked.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.