requiresource-mapsgulp-sourcemaps

Generate SourceMaps for a single js file which includes modules with npm require and gulp


I'll begin straight off with an example of my code structure. Assume the following three trivial files reside inside the same directory called /path/from/root/js/src

module1.js:

console.log(1);

module2.js:

console.log(2);

app.js:

require('./module1');
require('./module2');

Then, I am using the following gulp task to compile javascript into one file with gulp:

var gulp = require('gulp');
var sourcemaps  = require('gulp-sourcemaps');
var path = require('path');
var browserify = require('gulp-browserify');

gulp.task('default', function() {
    gulp.src(['./js/src/app.js'])
        .pipe(sourcemaps.init())
        .pipe(browserify()).on('error', function(err){
            console.log(err);
        })
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest(function( file ) {
            file.base = path.dirname(file.path);
            return path.join(path.dirname(file.path), '/../');
        }))
});

After running gulp I am getting the compiled javascript app.js which just logs 1 2 and an app.js.map as expected, but there is no reference to the original file in the browser.

You can check that by looking at the console lines 1 and 2, they are referenced by app.js, not by module1|2.js. If I needed to fix a bug I'd have no idea which file is generating the console notations in the future as the files grow bigger in my project.

What am I doing wrong? Am I not using the sourcemaps correctly?

The app.js.map file doesn't reference the modules, it looks like this:

{
    "version":3,
    "names":[],
    "mappings":"",
    "sources":["app.js"],
    "sourcesContent":["require('./module1');\r\nrequire('./module2');"],
    "file":"app.js"
}

Solution

  • I have found a more relative solution to the problem, so I'm creating a new answer for it. I have noticed that the gulp-browserify package I was using was deprecated, so I checked for an updated usage.

    My package.json dependencies are:

    "devDependencies": {
        "babel-preset-es2015": "^6.24.1",
        "babelify": "^7.3.0",
        "browserify": "^14.4.0",
        "gulp": "^3.9.1",
        "gulp-sourcemaps": "^2.6.0",
        "gulp-uglify": "^3.0.0",
        "gulp-util": "^3.0.8",
        "vinyl-buffer": "^1.0.0",
        "vinyl-source-stream": "^1.1.0"
    }
    

    My gulpfile.js for a basic build looks like this:

    'use strict';
    
    var browserify = require('browserify');
    var gulp = require('gulp');
    var source = require('vinyl-source-stream');
    var buffer = require('vinyl-buffer');
    var uglify = require('gulp-uglify');
    var sourcemaps = require('gulp-sourcemaps');
    var gutil = require('gulp-util');
    
    gulp.task('default', function () {
        // set up the browserify instance on a task basis
        var b = browserify({
            entries: './js/src/app.js',
            debug: true
        }).transform("babelify", {presets: ["es2015"]});
    
        return b.bundle()
            .pipe(source('app.js'))
            .pipe(buffer())
            .pipe(sourcemaps.init({loadMaps: true}))
            // Add transformation tasks to the pipeline here.
            //.pipe(uglify())
            .on('error', gutil.log)
            .pipe(sourcemaps.write('./'))
            .pipe(gulp.dest('./js/'));
    });
    

    For a production build, you can uncomment the uglify command. Babelify is there to allow ES5 syntax (didn't test, but probably you can instead use the *2017 package too).

    Sources:
    1. Gulp setup for Browserify
    2. Babel setup for Browserify