grunt-contrib-uglify
has a sourceMapIn
option that allows you to specify the location of an input source map file from an earlier compilation - which in your scenario is the browserify
task.
However, whilst setting browserifyOptions: { debug: true }
in your browserify
task does generate an inline source map in the resultant .js
file (i.e. in build/myapp.js
), the crux of the problem is twofold:
We don't have an external source map file that we can configure the sourceMapIn
option of the subsequent grunt-contrib-uglify
task to utilize.
grunt-browserify
doesn't provide a feature to create an external .map
file, it only creates them inline (see here)
To address the aforementioned issue consider utilizing grunt-extract-sourcemap to extract the inline source map from build/myapp.js
(i.e. from the output file generated by your browserify
task) after it has been produced.
Gruntfile.js
The following gist shows how your Gruntfile.js should be configured:
module.exports = function (grunt) {
grunt.initConfig({
browserify: {
myapp: {
options: {
transform: ['babelify'],
browserifyOptions: {
debug: true
},
},
src: 'src/index.js',
dest: 'build/myapp.js'
}
},
extract_sourcemap: {
myapp: {
files: {
'build': ['build/myapp.js']
}
}
},
uglify: {
options: {
sourceMap: true,
sourceMapIn: 'build/myapp.js.map'
},
target: {
src: 'build/myapp.js',
dest: 'build/myapp.min.js'
}
}
});
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-extract-sourcemap');
grunt.loadNpmTasks('grunt-contrib-uglify');
// Note the order of the tasks in your task list is important.
grunt.registerTask('default', ['browserify', 'extract_sourcemap', 'uglify']);
};
Explanation
First the browserify
task is invoked which outputs a new file (i.e. build/myapp.js
) containing your bundled JavaScript and an "inlined" source map info. If you were to inspect the content of build/myapp.js
at this stage it includes something like the following at the end:
//# sourceMappingURL=data:application/json;charset=utf-8;base64, ...
Next the extract_sourcemap
task is invoked. This essentially extracts the "inlined" source map info from build/myapp.js
and writes it to a new file named myapp.js.map
which is saved in your build
directory.
The original "inlined" source map info in build/myapp.js
is replaced with a link to the newly generated source map file, i.e. myapp.js.map
. If you inspect the content of build/myapp.js
you'll now notice the following at the end of the file instead:
//# sourceMappingURL=myapp.js.map
Lastly the uglify
task is invoked. Notice how its sourceMapIn
option is configured to read build/myapp.js.map
, i.e the source map file we generated at step 2.
This task creates your desired build/myapp.min.js
file containing; your minified JS, and a link to a newly generated source map file build/myapp.min.js.map
.
Note The final resultant file (i.e. build/myapp.min.js
) now correctly maps back to the original src/index.js
file and any file(s) that index.js
itself may have import
'ed or require()
'd