Search code examples
node.jsgruntjsgrunt-contrib-uglifygrunt-contrib-concat

Uglify or concat a JavaScript file conditionallly


I have in my Scripts folder a "Lib" folder and an "App" folder.

The Lib folder contains 3rd part library JavaScript files. Some of these are minified without the original sources, others we have the original sources for.

The App folder contains all of our own JavaScript files, all of which are not minified.

I'm new to Grunt but I have a gruntfile which does the following:

  • Uglifies all the JS files in the Lib folder and produces minified versions with sourcemaps.
  • Uglifies all the JS files in the App folder and produces minified versions with sourcemaps.

Obvious problem: some of the files in the Lib folder are minified, so minifying them again/generating source maps is a bad idea and can fail for various reasons.

My solution: I run Uglify only on .js files in the Lib folder into lib-unmin.min.js. I then concat all the already minified files into a lib-min.min.js file, then I concat both those files together to get lib.min.js.

The new problem What if I can't concat the already minified scripts to the end of the other minififed scripts without it breaking?

I have a dependency issue like this:

  • scripts/lib/a.js (required for b to run)
  • scripts/lib/b.min.js (required for c to run)
  • scripts/lib/c.js (required for the App scripts to run)

If I have an array of these file paths in my gruntfile, in that order, what's the easiest way of uglifying/concating all the files into a single minified JS file in that order, making sure we don't attempt to minify the minified file?

What do other developers do in similar situations?

Thanks!


Solution

  • I like to concat the files then uglify all of them together. This way uglify makes sure there aren't duplicate variable values overriding each other when it compresses the variable names.

    You can bundle as many files as you want in the concats. Make different concat groups to uglify together and maintain the 'first, second, third, ...' order like this:

    module.exports = function(grunt) {
      grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        uglify: {
          app: {
            options: {
              sourceMap: true,
              sourceMapName: 'build/maps/map.map'
            },
            files: {
              'build/app.min.js': ['build/js/app-first-unmin.js', 'build/js/app-second-min.js', 'build/js/app-third-unmin.js']
            }
          }
        },
    
        concat: {
          options: {
            separator: ';'
          },
          firstUnminified: {
            src: [
              'lib/underscore.js'
            ],
            dest: 'build/js/app-first-unmin.js'
          },
          secondMinified: {
            src: [
              'lib/moment.min.js'
            ],
            dest: 'build/js/app-second-min.js'
          },
          thirdUnminified: {
            src: [
              'lib/favico.js'
            ],
            dest: 'build/js/app-third-unmin.js'
          }
        },
      });
    
      grunt.loadNpmTasks('grunt-contrib-uglify');
      grunt.loadNpmTasks('grunt-contrib-concat');
    
      grunt.registerTask('default', ['concat:firstUnminified', 'concat:secondMinified', 'concat:thirdUnminified','uglify']);
    };