Let’s face it. Managing front end dependencies is still a headache. As developers, we have a plethora of options for building dependencies. Some of the tools off the top of my head are Grunt, Gulp, Broccoli, Component, NPM, and probably 5 more have been released since I started writing this post. In this tutorial, I am going to focus on Gulp but I’m sure it can be modified to work with any of the others.
Lately I’ve started a few side projects and wanted to quickly build out a MVP, minimal viable product, and Bootstrap paired with FontAwesome is a great way of doing this. The problem comes in with trying to automate the setup and have a nice clean package. Sure you can use a CDN but that limits your ability to modify variables and makes working offline difficult. By setting up Gulp we have all the sources available to modify and extend as we need.
Tonight after integrating these for the fourth time I thought it would be something good to share with the goal of benefiting others. From this point forward I will assume you have both bower and npm installed. If you do not then just do a little searching for installation instructions for your operating system. Neither should be too difficult.
The first step is to setup Bower. Create a new local directory and “cd” into it. Next run bower init
and following the instructions. I don’t believe any of the answers to the questions matter as this will only be used locally.
After that finishes install our required bower packages:
bower install bootstrap-sass-official --save
bower install fontawesome --save
By default, this will put them in the bower_components
directory which can be changed if you prefer. I will leave it as default.
Now we need to setup our gulp dependencies, which pull from NPM. Create a new package.json file and just add an empty object, {}
and save it.
Head back to the terminal and install our NPM dependencies:
npm install gulp gulp-ruby-sass gulp-notify gulp-bower --save-dev
This will install all the needed dependencies in a node_modules folder and also automatically update our package.json file with these dependencies.
Here is an example package.json showing the versions of dependencies I’m using:
{
"devDependencies": { "gulp": "^3.8.11", "gulp-bower": "0.0.10", "gulp-notify": "^2.2.0", "gulp-ruby-sass": "^0.7.1" } }
PLEASE NOTE: – gulp-ruby-sass is going through some changes. To follow along be sure and use the “^0.7.1″ version as I did.
Finally, we need to setup the gulpfile.js. Create this file and we’ll step through all the settings.
If you’ve looked at gulp files before then you might know they all start by including the dependencies by using the node require function. Here is the start:
var gulp = require('gulp'),
sass = require('gulp-ruby-sass')
notify = require("gulp-notify")
bower = require('gulp-bower');
These are everything we installed in the NPM step above and at this point just included and not actually doing anything.
Next up, I create a config object to hold various settings:
var config = {
sassPath: './resources/sass',
bowerDir: './bower_components'
}
I find by doing this it keeps the rest of the file simpler. The sassPath is the folder where I store the sass files I create. I’m using Laravel 5.0 and as you can see I just put them in resources/sass. These will end up being parsed and put in a ./public directory. Next is the bowerDir which is just the path to the bower_components.
Next let’s setup up our first gulp task for running bower.
gulp.task('bower', function() {
return bower()
.pipe(gulp.dest(config.bowerDir))
});
This task basically runs bower install but by including in the gulpfile other contributors only have to run gulp bower and have them all setup and ready.
Now that we have FontAwesome in bower_components we need to move the fonts out and place them into the ./public directory. Here is a simple move task to handle this:
gulp.task(‘icons’, function() {
return gulp.src(config.bowerDir + ‘/fontawesome/fonts/*.‘)
.pipe(gulp.dest(‘./public/fonts’));
});
All this is doing is taking whatever is in bower_components/fontawesome/fonts/ directory and moving those to ./public/fonts.
The next piece to the puzzle is setting up Sass and linking bootstrap and fontawesome into our path so our sass files can access them. Here is the task:
gulp.task('css', function() {
return gulp.src(config.sassPath + '/style.scss')
.pipe(sass({
style: 'compressed',
loadPath: [
'./resources/sass',
config.bowerDir + '/bootstrap-sass-official/assets/stylesheets',
config.bowerDir + '/fontawesome/scss',
]
})
.on("error", notify.onError(function (error) {
return "Error: " + error.message;
})))
.pipe(gulp.dest('./public/css'));
});
This task is a little complex but shouldn’t be to difficult to follow. The important parts of this task is the loadPath which tells gulp-ruby-sass all the locations it should look for files. The .on(“error” uses the notify plugin to alert something failed in the build, and the auto prefix is just a nicety that automatically creates vendor prefixes.
With this setup our main style.scss can import bootstrap and fontawesome easily. Here is an example:
@import url(http://fonts.googleapis.com/css?family=Raleway:400,700,300);
$font-family-base: 'Raleway', sans-serif;
// Import bootstrap and fontawesome
@import "bootstrap";
@import "font-awesome";
//...
I imported a new font and set it as bootstraps $font-family-base. When bootstrap is later pulled in it will see the variable is defined and use our setting. You can also do this for any bootstrap variables.
Finally, we are almost finished. Now we need a watch task and a default task.
// Rerun the task when a file changes
gulp.task('watch', function() {
gulp.watch(config.sassPath + '/**/*.scss', ['css']);
});
gulp.task('default', ['bower', 'icons', 'css']);
The first is the watch task which just listens for changes in the path and then runs the “css” task. Finally we have a default task which when called runs bower, icons, and the css task. This is useful so contributors can pull down your code, cd into it, run npm install, and finally gulp. Everything should be easily shared and used.
If you would like to see the final files used for this tutorial take a look at this demo repo. Also if you have any questions or if anything isn’t clear let me know in the comments.