Sumit Paliwal
Sumit Paliwal

Reputation: 395

Debug Javascript with multi-level source maps

I have a lot of javascript files, which goes through grunt uglify and gets minified individually, and further, I am performing grunt concat on these to get a single bundled minified file with source map.

Ex.

a.js, b.js, c.js -> Uglify -> a.min.js, b.min.js,c.min.js -> concat -> bundle.min.js

With dev tools and source map, from bundle.min.js, I can trace back only up to a.min.js/b.min.js/c.min.js. Where as my goal is to use source map to trace back up to a.js/b.js/c.js.

Upvotes: 0

Views: 352

Answers (1)

RobC
RobC

Reputation: 24962

Your requirement can be achieved, however you'll need to change the order of your tasks to the following instead:


a.js, b.js, c.js --> concat --> bundle.js --> uglify --> bundle.min.js


Note: The order of the tasks has been changed to concatenate the individual .js files before uglifying the resultant output.

Why is it necessary to change the order of tasks?

Because grunt-contrib-uglify provides the sourceMapIn option, whilst grunt-contrib-concat simply doesn't. Besides it's typical practice to concatenate files before uglifying them.

The sourceMapIn option is described as follows:

sourceMapIn

Type: String Function

Default: undefined

The location of an input source map from an earlier compilation, e.g. from CoffeeScript. If a function is provided, the uglify source is passed as the argument and the return value will be used as the sourceMap name. This only makes sense when there's one source file.

Gruntfile.js

Your Gruntfile.js can be configured something like this:

module.exports = function(grunt) {

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

  grunt.initConfig({
    concat: {
      options: {
        // ...
        sourceMap: true,
        sourceMapName: 'dist/js/bundle.map' // Specify path/name for sourceMap
      },
      my_target: {
        src: ['src/js/a.js', 'src/js/b.js', 'src/js/c.js'],
        dest: 'dist/js/bundle.js',
      },
    },
    uglify: {
      options: {
        // ...
        sourceMap: {
          includeSources: true
        },
        sourceMapIn: 'dist/js/bundle.map', // Specify the same path/name as
                                           // the `sourceMapName` value
                                           // in the `concat` task
      },
      my_target: {
        files: {
          'dist/js/bundle.min.js': ['dist/js/bundle.js']
        }
      }
    }
  });

  // Note we run the `concat` task before the `uglify` task.
  grunt.registerTask('default', ['concat:my_target', 'uglify:my_target']);
};

Notes:

  1. The path value specified for the concat.options.sourceMapName and uglify.options.sourceMapIn must be the same, e.g. dist/js/bundle.map.

  2. The concat task must run before the uglify task.

  3. The src and dest paths for both tasks will need to be defined as per your projects requirements.

Upvotes: 3

Related Questions