Getting up and running with Jekyll, Gulp and LiveReload

While the build process in Jekyll works great, it didn’t quite fit my requirements and I wanted more control. While some of the things that I required could be added using custom rake tasks, I found Gulp could handle all of this and bring a lot more benefits to the table at the same time.

One of the immediate advantages of using Gulp is that I could utilise LibSass over Ruby Sass, this offers a noticeable improvement in build time

Apart from improved build times we can do a lot more with gulp and there are a wealth of plugins available such as LiveReload that can greatly improve your workflow.

Getting started

To get going you will need to create a new Jekyll project or you can use an existing one that you wish to add gulp to. Firstly you will need to add a package.json in the root of you project with the following content in it or add these dependencies to an already existing one.

{
  "dependencies": {
    "express": "^4.12.3",
    "gulp": "^3.8.7",
    "gulp-sass": "~1.0.0",
    "gulp-shell": "~0.3.0",
    "gulp-util": "~3.0.4",
    "gulp-livereload": "~1.3.1",
    "tiny-lr": "~0.1.5"
  }
}

As we won’t be using Jekyll for compiling our stylesheets and we will be installing the above node packages we need to tell Jekyll to ignore these by adding the below to your Jekyll _config.yml

# Ignore when compiling
exclude:
  - _sass
  - node_modules
  - gulpfile.js
  - package.json

Once you have completed all of the above, you will then need to run an npm install to install the dependencies you just added. Then once everything is installed you can then move on to creating the gulpfile.

Creating the gulpfile

First off create an empty gulpfile.js in the root of your project. Inside of the gulpfile is where we can define any Gulp tasks that are required, but first we need to load Gulp itself and any plugins that the tasks we create will depend on. We can do this by adding the code below to the top of our gulpfile.

// gulpfile.js
var gulp     = require('gulp'),
express      = require('express'),
sass         = require('gulp-sass'),
shell        = require('gulp-shell'),
util         = require('gulp-util'),
livereload   = require('gulp-livereload'),
lr           = require('tiny-lr'),
server       = lr();

This will load Gulp and all the additional plugins you added through Npm earlier. Now we can move on to defining our first gulp task which will compile your Sass stylesheets back into css.

Compiling Sass stylesheets

A gulp task typically contains a number of steps or pipes and usually starts with a gulp.src declaration which in this case points to your master Sass stylesheet “_sass/styles.scss”. We then pipe the source file through the sass() method that is an instance of the Gulp Sass plugin we installed earlier and then finally we specify the destination we wish the outputted, compiled css file to be saved in.

// Build stylesheets
gulp.task('sass', function() {
  return gulp.src('_sass/styles.scss')
  .pipe(sass())
  .pipe(gulp.dest('assets/stylesheets'))
});

Now you have completed all of the above if you run “gulp sass” in your terminal everything should complete successfully and you will see your complied css file.

Integrating Jekyll with Gulp

We can now create a Gulp task to run our Jekyll builds for us, this will act as a wrapper around Jekyll’s own build task so that we can call it directly from within our Gulpfile.

// Jekyll Build
gulp.task('build', ['sass'], shell.task([ 'jekyll build' ]));

You should now be able to run “gulp build” and this will build you Jekyll site for you into the _site directory. This produces the same result as running “Jekyll Build” but as we added “[‘sass’]” as the second argument in our task definition this tells Gulp to always run our Sass task before running the build task which ensures all your stylesheets are compiled ready for Jekyll to use them as needed.

Watching for changes and implementing LiveReload

We can now compile all our stylesheets and build our Jekyll site directly with Gulp, the next step is to bring it all together. This task will need to do a number of things; start an expess server for serving our generated site and watch for file changes and regenerate our site when a change has been made. We can then use LiveReload to automatically update our browser with the latest changes without the need for constant refreshing.

// Watch and rebuild on change
gulp.task('default', function() {
  var app = express();
  app.use(express.static(__dirname + '/_site', { "no-cache": true }));
  var appserver = app.listen(3000, function (err) {
    if (err) {
      return console.log(err);
    }
    console.log(
        'Server listening on http://localhost:%s', 
        appserver.address().port
     );
  });

  var port = 35729;
  server.listen(port, function(err) {
    if (err) {
      return console.log(err);
    }

    console.log('LiveReload listening on port %s', port);

    gulp.watch([
      '_stylesheets/**/*.scss',
      '_includes/**/*.html',
      '_layouts/**/*.html',
      '_drafts/**/*',
      '_posts/**/*'
    ], ['build']);

  });
});

Where to next…

Gulp can do so much more than what we have covered so far, in a typical setup of mine I have Gulp compile my Coffescript, pull in any dependencies from Bower, minify and concatenate all my asset files for production and even compress my html.

What we have covered is only the tip of the Iceberg when it comes down to what can be achieved when using Gulp

I hope you enjoyed this article, I may plan to write a follow on explaining how to add Coffescript support and some extra Gulp tasks for preparing your code for production. If you would like to see this please let me know through twitter and share this article below, Thanks for reading.