Getting gulp-sourcemaps to map correctly with a series of plugins

1.1k views Asked by At

I have a git repo with multiple plugins (1 main one and several that are only intended to work with the main one). I am using this approach for distribution, since bower doesn't provide a way to have more than one plugin per git repo.

So, I need to minify each plugin, create a sourcemap for each plugin, and drop each one into an individual distribution folder that corresponds to a git submodule, which by convention I am naming the same as the plugin to make it simple. I came up with the following Gulp script that does that all in one step, which is mostly based off of the answers I found here.

return gulp.src(['./jquery.dirtyforms.js', './helpers/*.js', './dialogs/*.js'], { base: './' })
    .pipe(jshint())
    .pipe(jshint.reporter(stylish))
    .pipe(rename(function (path) {
        var baseName = path.basename;
        var dirName = path.dirname;
        if (dirName == 'helpers' || dirName == 'dialogs') {
            path.basename = 'jquery.dirtyforms.' + dirName + '.' + baseName;
            console.log(path.basename);
        }
        path.dirname = path.basename;
    }))
    .pipe(gulp.dest(distributionFolder))
    .pipe(sourcemaps.init())
    .pipe(rename(function (path) {
        var baseName = path.basename;
        var dirName = path.dirname;
        if (dirName == 'helpers' || dirName == 'dialogs') {
            path.basename = 'jquery.dirtyforms.' + dirName + '.' + baseName;
            console.log(path.basename);
        }
        path.dirname = path.basename;
        path.extname = '.min.js';
    }))
    .pipe(uglify({
        outSourceMap: true,
        sourceRoot: '/'
    }))
    .pipe(gulp.dest(distributionFolder))
    .pipe(sourcemaps.write('.', {
        includeContent: true,
        sourceRoot: '/'
    }))
    .pipe(gulp.dest(distributionFolder));

It does exactly what I want except for one thing. The sourcemap file that is generated for each plugin includes the subdirectory in the path. Since the final destination of the plugin won't include this path, this is invalid.

In the jquery.dirtyforms.min.js.map file:

{"version":3,"sources":["jquery.dirtyforms/jquery.dirtyforms.min.js"]...

Should be

{"version":3,"sources":["jquery.dirtyforms.min.js"]...

And in the jquery.dirtyforms.min.js file:

//# sourceMappingURL=../jquery.dirtyforms/jquery.dirtyforms.min.js.map

Should be

//# sourceMappingURL=jquery.dirtyforms.min.js.map

I dug through the source of gulp-sourcemaps to try to find an option to override the file name, but there doesn't seem to be one.

Two possible solutions I came up with for this are:

  1. Do a replace in each of the files using a regular expression
  2. Generate the files in the distributionFolderand then move them to the correct subfolder after they are generated

But both of these seem like hacks. It would be better if the stream created them correctly in the first place. Is there a way to make that so?

1

There are 1 answers

0
NightOwl888 On BEST ANSWER

I ended up going with the second option I mentioned - that is, generate the minified files in the distributionFolder (now settings.dest) and then moved them with separate copy and delete tasks.

var gulp = require('gulp'),
    uglify = require('gulp-uglify'),
    jshint = require('gulp-jshint'),
    stylish = require('jshint-stylish'),
    rename = require('gulp-rename'),
    sourcemaps = require('gulp-sourcemaps'),
    del = require('del');

var settings = {
    baseProject: 'jquery.dirtyforms',
    src: ['./jquery.dirtyforms.js', './helpers/*.js', './dialogs/*.js'],
    dest: './dist/'
};

// Moves the .js files to the distribution folders and creates a minified version and sourcemap
gulp.task('build', ['copy-minified'], function (cb) {
    del([settings.dest + '*.js', settings.dest + '*.map'], cb);
});

gulp.task('copy-minified', ['uglify'], function () {
    return gulp.src([settings.dest + '*.js', settings.dest + '*.map'], { base: './' })
        .pipe(rename(function (path) {
            console.log('moving: ' + path.basename)
            path.dirname = path.basename.replace(/\.min(?:\.js)?/g, '');
        }))
        .pipe(gulp.dest(settings.dest));
});

gulp.task('uglify', ['clean', 'test'], function () {
    return gulp.src(settings.src, { base: './' })
        .pipe(rename(function (path) {
            var baseName = path.basename;
            var dirName = path.dirname;
            if (dirName == 'helpers' || dirName == 'dialogs') {
                path.basename = settings.baseProject + '.' + dirName + '.' + baseName;
            }
            path.dirname = path.basename;
        }))
        .pipe(gulp.dest(settings.dest))
        .pipe(sourcemaps.init())
        .pipe(rename(function (path) {
            path.dirname = '';
            path.extname = '.min.js';
        }))
        .pipe(uglify({
            outSourceMap: true,
            sourceRoot: '/'
        }))
        .pipe(gulp.dest(settings.dest))
        .pipe(sourcemaps.write('.', {
            includeContent: true,
            sourceRoot: '/'
        }))
        .pipe(gulp.dest(settings.dest));
});

// Tests the source files (smoke test)
gulp.task('test', function () {
    return gulp.src(settings.src, { base: './' })
        .pipe(jshint())
        .pipe(jshint.reporter(stylish));
});

Maybe there is a better alternative that isn't such a hack, but this worked for me.