grunt.js - Multiple destinations when minifying files

Problem

My grunt.js has a typical minification task:

min: {
    dist: {
        src: ['dist/precook.js'],
        dest: 'dist/precook.min.js'
    }
}

What is the simplest way to have multiple dest files? I'd like to minify into:

  • dist/precook.min.js
  • example/js/vendor/precook.min.js

The built-in min task doesn't appear to support multiple destinations, so I assume this can be achieved via a simple "copy" task. Can someone please point me in the right direction?

Problem courtesy of: Matt Stone

Solution

I'd use grunt-contrib-copy plugin:

Install with npm:

npm install grunt-contrib-copy

Modify grunt.js (add copy task definition and load copy plugin):

    ...
    copy: {
        dist: {
            files: {
                'example/js/vendor/': 'dist/precook.min.js'
            }
        }
    }
    ...

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

Optionally register copy in to grunt's default task.

The added beauty here is that you can now perform all other copy tasks as well. Even patterns are supported, like copy all minified files ('dist/*.min.js').

Solution courtesy of: jsalonen

Discussion

Had a similar problem and created a grunt multi-task that runs a list of specified tasks on multiple directories

Usage for the exact case: ```

min: {
    dist: {
        src: ['dist/precook.js'],
        dest: 'dist/precook.min.js'
    }
},
multidest: {
    minifiedFiles: {
        tasks: ['min'],
        dest: [
            'dist/precook.min.js',
            'example/js/vendor/precook.min.js'
       ]
    }
}

```

Discussion courtesy of: erjitka

This is an alternative approach (next to @jalonen's solution) which may to interesting to you, IF you are using requirejs to modularize your project, then you can use the requirejs optimizer to minify your modules.

First of all, you need to add grunt-contrib-requirejs to your project:

npm install grunt-contrib-requirejs --save-dev

Grunt configuration:

        requirejs: {
            production:{
                options:{
                    // don't include libaries when concatenating/minifying
                    paths:{
                        angular:'empty:',
                        jquery:'empty:'
                    },
                    baseUrl:'path/to/src/js',
                    dir:'path/to/target/js',
                    // keeps only the combined files
                    removeCombined:true,
                    modules:[
                        {name:'app', exclude: ['moduleA', 'moduleB']},
                        {name:'moduleA'},
                        {name:'moduleB'}
                    ]
                }
            }
        }
        ...

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

Explanation:

Let's say you have this dependency tree (-> means depends on):

app -> moduleA -> moduleA1
               -> moduleA2              
app -> moduleB -> moduleB1
               -> moduleB2            

After minifying you will have three files:

  • app (minified version of app)
  • moduleA (minified version of moduleA, moduleA1, and moduleA2)
  • moduleB (minified version of moduleB, moduleB1, and moduleB2)
Discussion courtesy of: asgoth
concat: {
            css: {
                src: ['UI.controls/assets/css/*.css'],
                dest: 'UI.controls/assets/css/min/production.css'
            },

            js: {
                src: ['UI.controls/assets/js/*.js'],
                dest: 'UI.controls/assets/js/min/production.js'
            },

            js2: {
                src: ['UI.core/assets/js/*.js'],
                dest: 'UI.core/assets/js/min/production.js'
            }

        },

        cssmin: {
            css: {
                src: 'UI.controls/assets/css/min/production.css',
                dest: 'UI.controls/assets/css/min/production.min.css'
            }
        },

        uglify: {
            js: {
                src: 'UI.controls/assets/js/min/production.js',
                dest: 'UI.controls/assets/js/min/production.min.js'
            },

            js2: {
                src: 'UI.core/assets/js/min/production.js',
                dest: 'UI.core/assets/js/min/production.min.js'
            }
        },


        watch: {
            css: {
                files: ['UI.controls/assets/css/*.css'],
                tasks: ['concat:css', 'cssmin:css']
            },
            js: {
                files: ['UI.controls/assets/js/*.js'],
                tasks: ['concat:js', 'uglify:js']
            },

            js2: {
                files: ['UI.core/assets/js/*.js'],
                tasks: ['concat:js', 'uglify:js']
            }

        }
Discussion courtesy of: Dally S

This recipe can be found in it's original form on Stack Over Flow.