Browserify in Gulp with Correct Source Maps

To use browserify in gulp, one should not use a plugin, but rather one of gulp’s recipes (at least for now). Unfortunately, integrating browserify into gulp is not that easy, especially when it comes to source maps.

dist
index.html
logic
whenready
index.js
index.js
node_modules
gulpfile.js
The test project’s directory layout

When using the recipe with source maps from gulp’s docs on a small test project, source files get very odd paths assigned in the maps. Folders are nested multiple times, making it hard to find a file. With the recipe presented here on the other hand, files get represented with their correct paths in the source maps.

Before:
The sourcemap from the official recipe contains paths like logic/logic/logic/index.js
After:
The sourcemap from the presented recipe has correct paths

The gulp configuration looks like this:

testproject/gulpfile.js download
const gulp = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const transform = require('vinyl-transform');
const browserify = require('browserify');
const uglify = require('gulp-uglify');
const path = require('path');

function logic() {
	return gulp.src('logic/*.js', {read: false})
		.pipe(transform(filepath =>
			browserify(filepath, {
				debug: true
			})
			.plugin('browserify-sourcemap-root-transform', {basedir: path.resolve('.')})
			.bundle()
			.on('error', function(error) {
				console.error(error.stack ? error.stack : error);
				this.emit('end');
			})
		))
		.pipe(sourcemaps.init({loadMaps: true}))
		.pipe(uglify())
		.pipe(sourcemaps.write('.', {sourceRoot: '/'}))
		.pipe(gulp.dest('./dist'));
}

gulp.task(logic);

The example is written for Gulp 4. It also passes the code to uglify, to demonstrate that we have a normal vinyl stream after browserify and source maps work as expected. You can install all used packages by running

npm i --save-dev gulpjs/gulp#4.0 gulp-sourcemaps vinyl-transform browserify browserify-sourcemap-root-transform gulp-uglify

Remarks

The recipe uses a normal gulp.src vinyl stream to select the entry points. I think this approach is easier than the recipe with globs. Be aware, though, that browserify will read the entry points and all referenced files from disk. So the files must exist and plugins applied to the stream before browserify will have no effect.