I'm trying to compile a React app, append a hash to the output filename and produce a revision manifest, so that I can tell the browser to cache it forever. The problem is that the dozen or so tools involved don't all work together perfectly, at least as far as I can figure out by trying to assimilate all of their readmes and juggle .pipe
calls.
Gulpfile: gist
Gulp task:
gulp.task( 'compile:js', function() {
var browserifyTransform = transform( function( filename ) {
return browserify( filename )
.transform( reactify )
.bundle();
});
return gulp.src( 'src/index.js' )
.pipe( browserifyTransform )
.pipe( sourcemaps.init({ loadMaps: true }))
.pipe( uglify() )
.pipe( rev() )
.pipe( gulp.dest( 'static/dist' ));
});
update Simplified version, same error:
gulp.task( 'compile:js', function() {
var browserifyTransform = transform( function( filename ) {
return browserify( filename )
.transform( reactify )
.bundle();
});
return gulp.src( 'src/index.js' )
.pipe( browserifyTransform )
.pipe( gulp.dest( 'static/dist' ));
});
Error stack:
[15:55:04] Using gulpfile ~/Projects/pixsplodr/gulpfile.js
[15:55:04] Starting 'compile:js'...
Error: write after end
at writeAfterEnd (/home/dan/Projects/pixsplodr/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js:161:12)
at Labeled.Writable.write (/home/dan/Projects/pixsplodr/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js:208:5)
at write (_stream_readable.js:601:24)
at flow (_stream_readable.js:610:7)
at _stream_readable.js:578:7
at process._tickCallback (node.js:419:13)
Well, I have solution that satisfies my requirements, but it isn't perfect.
gulp.src
I am also using gulp-rev to append a hash to generated filenames, and to create a manifest that maps them to their original filename.
I was having trouble with source maps earlier too, but I have found that using Browserify transforms and settings seems to work better than using Gulp plugins on Browserify's output. That might be entirely due to user error, but I have been seeing so many conflicting Browserify / Gulp examples and minimal examples that I was unable to extend in an intuitive way, that I am just glad to have a working build with all of the features that I wanted.
var gulp = require( 'gulp' );
var gutil = require( 'gulp-util' );
var watchify = require( 'watchify' );
var browserify = require( 'browserify' );
var source = require( 'vinyl-source-stream' );
var buffer = require( 'vinyl-buffer' );
var sass = require( 'gulp-sass' );
var _ = require( 'lodash' );
var rev = require( 'gulp-rev' );
// Dev build
gulp.task( 'watch', [ 'sass' ], function() {
gulp.watch( 'node_modules/quiz/style/**/*.scss', [ 'sass' ]);
builder( './src/app/index.js', true ).bundle( './dist/static', 'quiz-app.min.js' );
});
// Production build
gulp.task( 'build', [ 'sass' ], function() {
builder( './src/app/index.js', false ).bundle( './dist/static', 'quiz-app.min.js' );
});
// snip //
function builder( entry, isDev ) {
var bundler;
if( isDev ) {
bundler = watchify( browserify(
'./src/app/index.js',
_.extend( watchify.args, { debug: true })
));
} else {
bundler = browserify(
'./src/app/index.js'
);
}
bundler.transform( 'reactify' );
bundler.transform( 'es6ify' );
bundler.transform({ global: true }, 'uglifyify' );
bundler.on( 'log', gutil.log ); // Help bundler log to the terminal
function bundle( dest, filename ) {
return bundler.bundle()
.on( 'error', gutil.log.bind( gutil, 'Browserify error' )) // Log errors during build
.pipe( source( filename ))
.pipe( buffer() )
.pipe( rev() )
.pipe( gulp.dest( dest ))
.pipe( rev.manifest() )
.pipe( gulp.dest( dest ));
}
return { bundle: bundle };
}
I also tried just using the tools from NPM scripts, but I was unable to find a good way to do incremental builds while watching a set of files.