Skip to content

Instantly share code, notes, and snippets.

@oscar-g
Created October 10, 2015 18:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oscar-g/4ec52eacc3eb533ddd31 to your computer and use it in GitHub Desktop.
Save oscar-g/4ec52eacc3eb533ddd31 to your computer and use it in GitHub Desktop.
React js dev workflow gulp file
var gulp = require('gulp'),
source = require('vinyl-source-stream'),
browserify = require('browserify'),
watchify = require('watchify'),
gulpif = require('gulp-if'),
uglify = require('gulp-uglify'),
streamify = require('gulp-streamify'),
notify = require('gulp-notify'),
concat = require('gulp-concat'),
gutil = require('gulp-util'),
livereload = require('express-livereload'),
extReplace = require('gulp-ext-replace'),
babelify = require('babelify'),
mergeStream = require('merge-stream'),
del = require('del'),
htmlReplace = require('gulp-html-replace'),
gulpConcat = require('gulp-concat'),
styl = require('gulp-stylus');
var globalOpts = {
srcDir : './src/',
appDir : './src/app/',
clientDir : './src/client/',
cssFile : './src/styles/main.styl',
cssGlob : './src/styles/**/*.styl',
assetsGlob : './src/assets/**/*',
buildDir: './build/',
htdocsDir: './build/htdocs',
deps: [
'react',
'react/addons',
'react-router',
'react-dom',
'react-bootstrap',
'history',
'formsy-react',
'jquery'
]
};
/**
* The main gulp tasks
* taskName:dev for development
* taskName:dist for production
*/
/**
* Builds the app for development, including styles, livereload, server, and watches for changes
*/
gulp.task('default', ['dev']);
gulp.task('dev', ['app:dev', 'html:dev', 'styles:dev', 'assets', 'watch:styles', 'serve']);
/**
* Builds the app for production with minified code.
*/
// gulp.task('dist', ['app:dist', 'html:dist', 'styles:dist', 'assets', 'server:dist']);
//sub tasks below
/**
* Compiles the ReactJS app for development.
* Splits code into 2 bundles: app and development.
* Watches app bundle and regenrates on change.
*
* @see _process_bundle()
* @see _get_bundle()
*/
gulp.task('app:dev', ['clean'], function(){
var bnls = _get_bundle(true, globalOpts.clientDir + 'main.jsx'),
stream = mergeStream(),
app, vendor;
watchify(bnls.app).on('update', function(){
_process_bundle(bnls.app, 'APP', 'main.js', true);
});
app = _process_bundle(bnls.app, 'APP', 'main.jsx', true),
vendor = _process_bundle(bnls.vendor, 'VENDOR', 'vendors.jsx', true);
stream.add(app);
stream.add(vendor);
return stream;
});
/**
* Compiles the ReactJS app for production
*/
gulp.task('app:dist', ['clean'], function(){
var bnls = _get_bundle(false, globalOpts.clientDir + 'main.jsx');
return _process_bundle(bnls.app, 'APP', 'main.jsx', false);
});
/** Deletes the contents of the build/htdocs dir (except the css)*/
gulp.task('clean', function(){
return del([
'!' + globalOpts.htdocsDir + 'main.css',
globalOpts.htdocsDir + '**/*'
], {
dot: true
});
});
/** Deletes the css*/
gulp.task('clean:css', function(){
return del(globalOpts.htdocsDir + 'main.css');
});
/**
* Copies the index.html (app entry point)
* Injects a live reload script.
*/
gulp.task('html:dev', ['clean'], function(){
return gulp.src(globalOpts.clientDir + 'index.html')
.pipe(htmlReplace({
'livereload': {
src: "document.write('<script src=\"http://' + (location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1\"></' + 'script>')",
tpl: "<script>%s</script>"
},
'scripts': {
src: ['/vendors.js', '/main.js']
}
}))
.pipe(gulp.dest(globalOpts.htdocsDir));
});
/**
* Copies the production index.html to the htdocs folder (app entry point)
*/
gulp.task('html:dist', ['clean'], function(){
return gulp.src(globalOpts.clientDir + 'index.html')
.pipe(htmlReplace({
'scripts': {
src: ['/main.js']
}
}))
.pipe(gulp.dest(globalOpts.htdocsDir));
});
/**
* Runs the development server
*/
gulp.task('serve', ['app:dev'], function(){
var server = require( globalOpts.srcDir + 'server/index.js')(true, globalOpts.htdocsDir);
livereload(server, {
watchDir: globalOpts.htdocsDir
});
server = server.listen(8889, function(){
console.log('Development server listening at http://localhost:%s', server.address().port);
});
});
/** Copies assets from the assets directory to the destination directory */
gulp.task('assets', ['clean'], function(){
return gulp.src(globalOpts.assetsGlob, {dot: true})
.pipe( gulp.dest(globalOpts.htdocsDir) );
});
/** Compiles un-minified styles for development */
gulp.task('styles:dev', ['clean:css'], function(){
return gulp.src(globalOpts.cssFile)
.pipe(styl())
.pipe(gulp.dest(globalOpts.htdocsDir));
});
/** Compiles minified styles for production */
gulp.task('styles:dist', ['clean:css'], function(){
return gulp.src(globalOpts.cssFile)
.pipe(styl({
compress: true
}))
.pipe(gulp.dest(globalOpts.htdocsDir));
});
/** watches styles for changes, runs styles: task */
gulp.task('watch:styles', function(){
return gulp.watch(globalOpts.cssGlob, ['styles:dev']);
});
/**
* Helper functions below
*/
/**
* Returns an object with the app bundle and (if dev) the vendor bundle
*/
function _get_bundle(dev, src) {
var opts = {
entries: [src],
transform: [babelify],
extensions: ['.jsx'],
cache: {},
packageCache: {},
debug: dev,
fullPaths: dev
},
bundle = browserify(opts),
bundles = {};
if (dev === true) {
globalOpts.deps.forEach(function (dep) {
bundle.external(dep);
});
bundles.vendor = browserify({
debug: true,
require: globalOpts.deps
});
}
bundles.app = bundle
return bundles;
}
/**
* Processes a bundle. Minifies when dev.
*/
function _process_bundle(bnl, name, src, dev) {
var start = Date.now();
return bnl.bundle()
.on('error', gutil.log)
.pipe(source(src))
.pipe(gulpif(!dev, streamify(uglify())))
.pipe(extReplace('.js'))
.pipe(gulp.dest( globalOpts.htdocsDir ) )
.pipe(notify(function () {
console.log(name + ' bundle built in ' + (Date.now() - start) + 'ms');
}));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment