Package management, build streams and live reload with Bower and gulp

Bower + Gulp + Sass

Asset management in web apps is often an afterthought, resulting in a convoluted mess of files and folders that becomes impossible to manage. You spend time making your code readable, manageable within a framework, and easy for your team to find. It’s now time to treat your Sass/CSS, Javascript and images as first-class citizens, right next to your code.

How many times have you been to, downloaded jquery.min.js, and moved it into your asset folder? And how many times have you had to update that file? And how do you keep track of files that are dependent on it? Or, more importantly, how do you make sure you’re not updating a plugin that requires a specific version of jQuery?

Enter Bower and gulp. And, as an added bonus, we’re going to do some live reloading. If this sounds similar to CodeKit, it is. The only difference is that it’s free, there’s no GUI, and it’s faster.

Node.js and npm

Before we begin, you’ll need to install Node.js and npm. npm is the Node Package Manager and is include with Node.js. Visit Node.js and click Install. Go through the install process. It’s easy.


Bower is a package manager developed by Twitter. It installs packages via git, which can contain anything. You can find Bower packages via the command line or via Bower’s online registry. A package could be Foundation, Bootstrap or even WordPress. For now, though, we’ll be using Bower to manage our SASS and JS.

To install Bower:

$ npm install -g bower

Next, head to your assets directory. I’m working with a bare bone Laravel project, and have created my asset directory as follows:

$ mkdir ~/gulp-project/app/assets/ && cd ~/gulp-project/app/assets/

We need to initialize Bower. Running this command will ask you a bunch of questions and will create a bower.json file.

$ bower init

Now let’s install our first package. We’re going to be working with Foundation on this project, as it has fantastic Sass support.

There are two ways to do this. You can either add your dependency (the package) to your bower.json file, or you can use the command line. To make things simple, let’s just use the command line:

$ bower install foundation

Foundation has been downloaded via git and installed into the assets/bower_components directory.

Now that we have Bower managing our assets, we can update via the command line, verify dependencies, and more. Read the Bower docs for more info.

Foundation setup

Since we are using Foundation Sass, we have a few things to do before we continue.

In the case of my Laravel project, the only files accessible by the public are in the /public directory, which I set as the http root. So I like to think of my ~/gulp-project/app/assets directory as the source files. Therefore, I’ll end up putting my minified CSS file in ~/gulp-project/public/assets/css/

I like to override some of Foundation’s odd defaults, like having Open Sans load automatically. As per the docs, I create a ~/gulp-project/app/assets/sass/_foundation_settings.scss file. In it, the following:

@import '../bower_components/foundation/scss/foundation/functions';

$include-open-sans: false !default;
$rem-base: 16px;
$row-width: rem-calc(1400);

First, you must import the Foundation functions file. After that, you can change any defaults you wish. Or, do nothing. Whatever works for your project.

Next, I create a ~/gulp-project/app/assets/sass/styles.scss file. In it, the following:

@charset 'UTF-8';
@import 'foundation_settings';
@import '../bower_components/foundation/scss/foundation/components/grid';

One of the huge benefits of using Sass is that you can pick and choose what you want to use from Foundation. I’m only going to be using the grid for now, but you can add any component you like.


Gulp is a streaming build system similar to Grunt, but faster. It has a much nicer configuration file and uses pipes for passing your files through plugins. Basically, you create a bunch of different tasks to perform while running gulp. These tasks can be minifying CSS, optimizing images, or any other boring tasks us developers usually do.

First, you’ll need to install gulp globally:

$ npm install gulp -g

Next, while in your project’s root (in thi case, ~/gulp-project/), install gulp locally:

$ npm install gulp gulp-util --save-dev

Since we’re going to be working with Sass, let’s make sure it’s installed:

$ gem install sass

Now we need to install some gulp plugins for our project. In this example, we’ll be using plugins that let us compile Sass to CSS and minify, an auto-prefixer, and live reloading.

$ npm install gulp-ruby-sass gulp-autoprefixer gulp-minify-css gulp-notify gulp-rename gulp-livereload tiny-lr gulp-cache --save-dev

Once this command has finished, you’ll need to create a gulpfile.js in your root. Add the following:

var gulp = require('gulp'),
sass = require('gulp-ruby-sass'),
autoprefixer = require('gulp-autoprefixer'),
minifycss = require('gulp-minify-css'),
rename = require('gulp-rename'),
concat = require('gulp-concat'),
notify = require('gulp-notify'),
livereload = require('gulp-livereload'),
lr = require('tiny-lr'),
server = lr();

What we’re doing here is loading gulp and all the plugins we need.

Now let’s create our first task. In this case, it’s our styles task. This goes in gulpfile.js.

gulp.task('styles', function() {
return gulp.src('app/assets/sass/styles.scss')
.pipe(sass({ style: 'expanded' }))
.pipe(autoprefixer('last 2 version', 'safari 5', 'ie 9', 'ios 6', 'android 4'))
.pipe(rename({ suffix: '.min' }))
.pipe(notify({ message: 'Style task completed.' }));

As you can see, gulp’s config is easy to read. Basically, we’re getting the source file, piping it to Sass, autoprefixing based on specific browsers (get more details here), adding .min to the outputted file, minifying the CSS, putting it in the destination, reloading the browser, and sending a notification to Mac OSX’s Notification Center. If you’re on Windows, just remove the notify pipe.

There’s a lot going on there, but it just makes sense.

Next, let’s run gulp to make sure it’s working. Make sure you’re in your project root and make sure you name the task (in this case, styles):

$ gulp styles

If successful, you should see:

[gulp] Using file /Users/donaldallen/Sites/sample-project/gulp-project/gulpfile.js
[gulp] Working directory changed to /Users/donaldallen/Sites/sample-project/gulp-project
[gulp] Running 'styles'...
[gulp] styles.min.css was reloaded.
[gulp] gulp-notify: [Gulp notification] Style task completed.
[gulp] Finished 'styles' in 629 ms

Great, it works. But who wants to run gulp styles or gulp scripts every time you update? Let’s use gulp watch to watch the files for changes, and have it reload your browser at the same time.

gulp.task('watch', function() {
server.listen(35729, function (e) {
if (e) {
return console.log(e)

var watcher =['app/assets/sass/*.scss'], ['styles']);

watcher.on('change', function(event) {
console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');

Now that we have a watch task, all we have to do is run the following command, keep Terminal open, and not worry about it again:

$ gulp watch

To enable live reloading, you must be using Chrome or Canary with the LiveReload plugin. When you’re on a page you want to live reload, you’ll need to click the LiveReload button in Chrome to activate the server.

That, in a nutshell, is gulp. There is so much more you can do, including compressing images and concatenating/minifying javascript. Now that you have a good understanding, you should head to the docs to learn more.


The nice thing about this setup is that you don’t need to worry if someone has CodeKit or something similar. Anyone on the team can take your project, gulp watch and not worry about any configuration problems.

I put my simple Laravel project on GitHub that also includes some other gulp tasks, like watching for changes to PHP files and refreshing the browser. If you want to run this project, you’ll need to run composer update in the root.

Leave a comment below if you have any questions!

  • This is pretty cool and helpful. Thanks :D

    • Donald Allen

      Glad you liked it! I’m going to do another blog post on using + everything else discussed here.

  • Nice article! Should I just put a package.json file in my root folder alongside my gulpfile.js?

    • Donald Allen

      package.json are for gulp packages. I haven’t had to worry about that, as the packages are managed by node and are kept in node_modules. Maybe I’m unclear on your question though, so let me know if I need clarification.

      • I’m very new to Gulp and Grunt so forgive me if I ask this in ignorance. If my Node Modules are not global but local to my laravel project, should I place the package.json file in the root folder and add my node dependencies to that?

  • gulp-concat is missing. Update your npm install command with this one:

    npm install gulp-concat gulp-ruby-sass gulp-autoprefixer gulp-minify-css gulp-notify gulp-rename gulp-livereload tiny-lr gulp-cache –save-dev

    Great post btw. Thanks a lot for your time.

  • Jason

    I haven’t been able to find an answer to this question all over google. Say, like most of us, I have older versions of foundation in projects I still maintain. I update the sass gem, now, I have syntax errors while trying to compile older foundation work. I use bower for foundation. It would be nice if my bower foundation file’s were dependent on having a certain version of Sass installed. Is there a way to make sure I can hand off my project as a whole, and not worry about a co-worker having a different version of sass? In the long term, how do we maintain older versions of projects using foundation when we are all using random sass versions? (the obvious answer is to update foundation, but still, there has to be a way to couple dependencies between versions sass and bower foundation) Any thoughts would be great. This is a real problem with bower libraries that rely on gems.

  • Stephen Hamilton

    I seem to be getting a consistent error even though (I am pretty sure) I hav followed exaclty as Don stated above:

    [14:36:12] ‘styles’ errored after 3.9 ms
    [14:36:12] TypeError: Arguments to path.join must be strings
    at f (path.js:204:15)
    at Object.filter (native)
    at Object.exports.join (path.js:209:40)
    at module.exports (D:xampphtdocsnewgardennode_modulesgulp-ruby-sassindex.js:61:15)
    at Gulp. (D:xampphtdocsnewgardengulpfile.js:15:7)
    at module.exports (D:xampphtdocsnewgardennode_modulesgulpnode_modulesorchestratorlibrunTask.js:34:7)
    at Gulp.Orchestrator._runTask (D:xampphtdocsnewgardennode_modulesgulpnode_modulesorchestratorindex.js:273:3)
    at Gulp.Orchestrator._runStep (D:xampphtdocsnewgardennode_modulesgulpnode_modulesorchestratorindex.js:214:10)
    at Gulp.Orchestrator.start (D:xampphtdocsnewgardennode_modulesgulpnode_modulesorchestratorindex.js:134:8)
    at D:UsersStephenAppDataRoamingnpmnode_modulesgulpbingulp.js:129:20

    Any thoughts?