Gulp: Splitting JS Compilation Into Sections

While developing Inform Mapper, I ran into a slight problem with gulp and cytoscape. I was running a gulp task to combine and minify all my js, but found that the task was taking 8 seconds, which was far too slow to easily develop in. After trail-and-error, I identified the culprit as cyotscape, which was taking 7.5 seconds to parse due to its size.

I would eventually move cytoscape to a cdn, but to resolve this issue while developing, I split up my gulp task into 2 parts: one that would compile the external scripts once, and another that would only check for that compiled file and then move onto generating the user scripts. Since my external scripts were at that point stabilized, this worked well. To avoid others from wasting time doing this, I wanted to publish the method:

var gulp = require('gulp');
var concat = require('gulp-concat');
var merge = require('merge-stream');
var plumber = require('gulp-plumber');
var del = require('del');
var uglify = require('gulp-uglify');
var fs = require('file-system');

gulp.task('clean_external_graph_js', function() {
	return del('inform_mapper/static/scripts/graph/external/external.min.js');
});

function generate_external_scripts( ) {
	return gulp.src([ 'inform_mapper/static/scripts/graph/external/*.js' ])
		.pipe(concat('external.min.js'))
		.pipe(uglify())
		.pipe(gulp.dest('inform_mapper/static/scripts/graph/external/'));
}

gulp.task('external_graph_scripts', ['clean_external_graph_js'], function() {
	return generate_external_scripts( );
});

gulp.task('clean_graph_js', function() {
	return del('inform_mapper/static/scripts/graph.min.js');
});

gulp.task('graph_scripts', ['clean_graph_js'], function() {
	try {
		fs.accessSync('inform_mapper/static/scripts/graph/external/external.min.js');
	} catch( ex ) {
		generate_external_scripts( );
	}
	
	var external_stream = gulp.src([ 'inform_mapper/static/scripts/graph/external/external.min.js' ])
		.pipe(plumber());

	var internal_stream = gulp.src(['inform_mapper/static/scripts/graph/graph_logic.js', 'inform_mapper/static/scripts/graph/graph.js'])
		.pipe(plumber())
		.pipe(concat('internal.min.js'))
		.pipe(uglify());

	var merged_stream = merge( external_stream, internal_stream )
		.pipe(plumber())
		.pipe(concat('graph.min.js'))
		.pipe(gulp.dest('inform_mapper/static/scripts/'));

	return merged_stream;
});

gulp.task('watch', function () {
	gulp.watch(['inform_mapper/static/scripts/graph/external/*.js', '!inform_mapper/static/scripts/graph/external/external.min.js'], ['external_graph_scripts']);
	gulp.watch(['inform_mapper/static/scripts/graph/*.js'], ['graph_scripts']);
});

The most important part of this script is the try/catch block. Since fs.accessSync is a synchronous call, our graph_scripts function will block until we create the necessary file.