← Back to all tutorials

Uglifying JavaScript

Install and configure the grunt-contrib-uglify plugin to minify JavaScript — reducing file size for faster production downloads.

Uglifying JavaScript

In the previous episodes, we concatenated JavaScript files into a single bundle and compiled SASS into CSS. Now it is time to uglify (minify) the JavaScript for production. Uglification reduces file size by removing whitespace, shortening variable names, and stripping comments — making your code download and execute faster.

What Does Uglify Do?

TechniqueBeforeAfter
Remove whitespacefunction add( a, b ) {function add(a,b){
Shorten variablesvar message = 'hello';var a='hello';
Remove comments// This adds two numbers(removed entirely)
Remove dead codeif (false) { ... }(removed entirely)
Simplify expressionsvar x = true;var x=!0;

A typical uglified file is 40-70% smaller than the original. For large applications, this saves significant bandwidth and load time.

Step 1: Install the Plugin

npm install grunt-contrib-uglify --save-dev

Step 2: Configure the Task

Add the uglify task to your Gruntfile.js initConfig:

uglify: {
    options: {
        banner: '/* <%= pkg.name %> - v<%= pkg.version %> - ' +
                '<%= grunt.template.today("yyyy-mm-dd") %> */\n',
    },
    build: {
        src: 'dist/js/bundle.js',
        dest: 'dist/js/bundle.min.js',
    },
},

Understanding the Configuration

PropertyValuePurpose
options.bannerComment stringA preserved comment prepended to the output — useful for copyright notices
build.src'dist/js/bundle.js'The concatenated file from the previous step
build.dest'dist/js/bundle.min.js'The minified output file

Notice the source is the output of the concat step — we concatenate first, then uglify the result. This is the correct pipeline order: concatuglify.

The grunt.template.today Helper

<%= grunt.template.today("yyyy-mm-dd") %>

This is a built-in Grunt helper that outputs the current date. Useful for build banners so you know when the file was last built.

Step 3: Load the Plugin and Update Tasks

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

grunt.registerTask('default', ['concat', 'sass:dev']);
grunt.registerTask('build', ['concat', 'uglify', 'sass:prod']);

The build task now runs all three steps in order: concatenate JavaScript, uglify the result, and compile SASS in compressed mode. The default task skips uglification since you want readable code during development.

Step 4: Run It

# Development (no uglification)
grunt

# Production (with uglification)
grunt build

# Just uglify
grunt uglify

The Output

The original dist/js/bundle.js might look like:

/* grunt-project - v1.0.0 */
// Module 1: Utility functions
function greet(name) {
    return 'Hello, ' + name + '!';
}

function add(a, b) {
    return a + b;
}
...

After uglification, dist/js/bundle.min.js looks like:

/* grunt-project - v1.0.0 - 2024-01-15 */
function greet(n){return"Hello, "+n+"!"}function add(n,t){return n+t}...

Uglify Options

OptionWhat It Does
mangleShorten variable and function names (default: true)
compressApply code transformations to reduce size (default: true)
beautifyFormat output with indentation (default: false)
bannerPrepend a string to the output (not removed by minification)
sourceMapGenerate a source map for debugging minified code
preserveCommentsKeep some or all comments (e.g., 'some' keeps comments with !)

Customizing Uglify Behavior

uglify: {
    options: {
        mangle: true,
        compress: {
            drop_console: true,    // Remove console.log statements
            dead_code: true,       // Remove unreachable code
        },
        banner: '/* © <%= pkg.name %> */\n',
        sourceMap: true,
    },
    build: {
        src: 'dist/js/bundle.js',
        dest: 'dist/js/bundle.min.js',
    },
},

The drop_console: true option is particularly useful — it automatically removes all console.log, console.warn, and console.error statements from your production build so debugging code never reaches users.

Source Maps

uglify: {
    options: {
        sourceMap: true,
        sourceMapName: 'dist/js/bundle.map',
    },
    build: {
        src: 'dist/js/bundle.js',
        dest: 'dist/js/bundle.min.js',
    },
},

A source map is a file that maps minified code back to the original source. When you open browser DevTools, the debugger shows your original readable code instead of the minified version. This makes it possible to debug production code.

The Complete Gruntfile

module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        concat: {
            options: {
                separator: ';\n',
                banner: '/* <%= pkg.name %> - v<%= pkg.version %> */\n',
            },
            dist: {
                src: ['src/js/*.js'],
                dest: 'dist/js/bundle.js',
            },
        },

        uglify: {
            options: {
                banner: '/* <%= pkg.name %> - <%= grunt.template.today("yyyy-mm-dd") %> */\n',
            },
            build: {
                src: 'dist/js/bundle.js',
                dest: 'dist/js/bundle.min.js',
            },
        },

        sass: {
            dev: {
                options: { style: 'expanded' },
                files: {
                    'dist/css/styles.css': 'src/scss/styles.scss',
                },
            },
            prod: {
                options: { style: 'compressed' },
                files: {
                    'dist/css/styles.min.css': 'src/scss/styles.scss',
                },
            },
        },
    });

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

    // Development: concat + readable CSS
    grunt.registerTask('default', ['concat', 'sass:dev']);

    // Production: concat + uglify + compressed CSS
    grunt.registerTask('build', ['concat', 'uglify', 'sass:prod']);

};

The Build Pipeline

StepTaskInputOutput
1concatsrc/js/*.js (multiple files)dist/js/bundle.js (one file)
2uglifydist/js/bundle.js (readable)dist/js/bundle.min.js (minified)
3sasssrc/scss/styles.scssdist/css/styles.css or .min.css

Key Takeaways

  • grunt-contrib-uglify minifies JavaScript by removing whitespace, shortening names, and stripping comments
  • Uglification typically reduces file size by 40-70%
  • The build pipeline runs in order: concatuglifysass
  • The banner option preserves a copyright comment at the top of the minified file
  • drop_console: true removes all console statements from production builds
  • Source maps allow you to debug minified code by mapping it back to the original source
  • Use default for development (readable) and build for production (minified) workflows