Boilerplate Template for Node.js and Backbone Using Gulp and Browserify
I’ve been working with Node.js and Backbone for a little over a year now and recently started a new side project in my spare time. Every time I start a project from the ground up, I have to sit down and think about things I probably haven’t in a while. For example, what’s the best way to organize my code, or how should my build process look?
Since I have recently gone through this, I wanted to share a boilerplate application I have put together for the Node.js/Backbone.js stack using Gulp and Browserify. This post isn’t an introduction to Node or Backbone (if you’re looking for that there is plenty of documentation to be found online), but more a look at my build process with Gulp and Browserify. The source code can be found here.
Getting Started
So, what are Gulp and Browserify and why are they useful? Simply enough, Gulp is a build runner that uses pipes to process data. Browserify is an awesome tool that allows you to write your client-side javascript code using CommonJS like modules (just like we use in Node.js), or in other words, using Browserify you can access modules in your client code using the require() method. The neat thing about this is that it essentially removes your need for Bower since you no longer have a need for front-end dependencies and backend-end dependencies in most cases.
* A quick note: Gulp has a Browserify module (gulp-browserify) which has been, for numerous reasons, blacklisted and shouldn’t be used anymore (see this article for details). So in my code I’m using vanilla Browserify with Gulp. This requires a little more work, as you’ll see, but it’s not to bad.*
So here are the objectives for my Gulp/Browserify build:
- Bundle all of my client-side Javascript code into one file and uglify. Pipe the result to our public folder.
- Compile my less files into one minified css file and pipe the result to my public folder.
- Create a dev task that starts the server and watches for changes in my Less or JavaScript files and “recompiles” the source code.
Let’s start by creating a task called Browserify. Here is my code:
gulp.task('browserify', function() { var b = browserify('./client/js/app.js', {debug: true}) return b.transform(hbsfy) .bundle() .pipe(source('app.browserified.js')) .pipe(gulp.dest('./build')) });
So there are a few things going on here that are worth talking about. I’m using the vanilla Browserify module, not gulp-browserify. Since native Browerserify doesn’t support streams, I need to use vinyl-streams so that it will play nicely with Gulp.
var source = require('vinyl-source-stream');
Passing the {debug:true} option into your browserify instance is all you need to create your source maps. Browserify also provides a mechanism to transform source code before being injected into the bundle. This will come in handy since I need a way to transform my handlebars templates into precompiled template functions. For this I’m using hbsfy, which compiles your handlebars templates into plain JavaScript.
var hbsfy = require('hbsfy');
After bundling, I’m sourcing it with my vinyl-streams and piping it to the build folder.
My uglify task is rather straight forward. It sources the app.browserified.js file and, depending on whether I’m in “development” or “production” mode, will uglify the file (I don’t uglify if in dev mode, as this will mess up the source maps and make debugging difficult).
// Only uglify if not in development var uglify = function() { return gulpif(process.env.NODE_ENV !== 'development', gulpuglify()); } gulp.task('uglify', function() { return gulp.src('build/app.browserified.js') .pipe(uglify()) .pipe(rename('app.min.js')) .pipe(gulp.dest('public/js')); });
Finally, for my less files, I have an index.less file that I use to import all of my bootstrap less components as well as my bootswatch theme. I want to use gulp-less to compile this into one css file, and then minify and uglify.
gulp.task('minify', ['styles'], function() { return gulp.src('./build/bundle.css') .pipe(minifyCSS()) .pipe(rename('app.min.css')) .pipe(gulp.dest('./public/css')) }); // Style tasks gulp.task('styles', function() { return gulp.src('./client/less/index.less') .pipe(less()) .pipe(prefix({ cascade: true })) .pipe(rename('bundle.css')) .pipe(gulp.dest('./build')) });
Now to put it all together. I created a task called dev, which relies on a watcher task that keeps an eye on my javascript/handlebars/less files and rebuilds and restarts the server when they change. The dev task uses gulp-nodemon so you can simply run the “gulp dev” and it should take care of everything and start your server. This eliminates you needing to manually call “gulp build” then “nodemon server.js” every time you make a change.
gulp.task('watch', function(done){ return runSequence('build', function() { gulp.watch('./client/js/**/*.js', ['build']); gulp.watch('./client/templates/*.hbs', ['build']); gulp.watch('./client/less/*.less', ['build']); done() }) }); gulp.task('dev', ['watch'], function() { nodemon({ script: 'server.js', delay: 2500 }) });
That’s all for now.
Reference: | Boilerplate Template for Node.js and Backbone Using Gulp and Browserify from our WCG partner Keyhole Software at the Keyhole Software blog. |