Conclusion

Learning Gulp : part 22 of 22 published on Aug 17, 2015

We started with no knowledge of gulp and then built out series of tasks from the simple to the complex.

We used the following plugins:

  • gulp-concat
  • gulp-jasmine
  • gulp-jsvalidate
  • gulp-markdown
  • gulp-minify-css
  • gulp-notify
  • gulp-rename
  • gulp-rimraf
  • gulp-tap
  • gulp-uglify
  • gulp-webserver

We also used other libraries as we developed including:

  • karma-jasmine
  • underscore
  • handlebars

We leveraged gulp’s watch tasks to watch for file changes and run our build scripts.

We also used gulp-webserver to provide a webserver to host our website along with enabling live reloading of our changes.

Finally we used gulp-tap with markdown and handlebars to generate pages with meta data and templates.

Our final gulpFile.js looks like:

// gulpfile.js
var gulp = require('gulp');
var concat = require('gulp-concat');
var clean = require('gulp-rimraf');
var cssmin = require("gulp-minify-css");
var jsValidate = require('gulp-jsvalidate');
var notify = require('gulp-notify');
var uglify = require('gulp-uglify');
var jasmine = require('gulp-jasmine');
var webserver = require('gulp-webserver');
var markdown = require('gulp-markdown');
var tap = require('gulp-tap');
var Handlebars = require('Handlebars');
var rename = require('gulp-rename');
var path = require('path');
var _ = require('underscore');

var Data = {
  pages: []
};

gulp.task('clean', [], function() {
  console.log("Clean all files in build folder");

  return gulp.src("build/*", { read: false }).pipe(clean());
});

gulp.task('css', ['clean'], function() {
  console.log("Concat, move, and minify all the css files in styles folder");
  return gulp.src("contents/styles/**.css")
      .pipe(concat('main.min.css'))
      .pipe(cssmin())
      .pipe(gulp.dest('build/styles'));
});

gulp.task('javascript', ['clean'], function () {
  console.log("Validate, Concat, Uglify, and Move all the javascript files");

  return gulp.src("contents/javascripts/**.js")
      .pipe(jsValidate())
      .on("error", notify.onError(function(error) {
        return error.message;
      }))
      .pipe(uglify())
      .pipe(concat('main.js'))
      .pipe(gulp.dest('build/javascripts'));
});

gulp.task('default', ['css', 'homepage', 'javascript']);

gulp.task('watch', ['default'], function() {
  return gulp.watch(['contents/**'], ['default']);
});

gulp.task('specs', function () {
  return gulp.src('specs/**.js')
    .pipe(jasmine());
});

gulp.task('spec-watch', function() {
  return gulp.watch(['specs/**.js', 'contents/javascripts/**.js'], ['specs']);
});

gulp.task('homepage', ['clean', 'generate_pages'], function() {
  return gulp.src("contents/index.hbs")
    .pipe(tap(function(file, t) {
      var template = Handlebars.compile(file.contents.toString());
      var html = template({ 
        title: "Gulp + Handlebars is easy",
        pages: Data.pages
      });
      file.contents = new Buffer(html, "utf-8");
    }))
    .pipe(rename(function(path) {
      path.extname = ".html";
    }))
    .pipe(gulp.dest("build"));
});

gulp.task('webserver', function() {
  return gulp.src('build')
    .pipe(webserver({ livereload: true }));
});

gulp.task('generate_pages', function() {
  // read the template from page.hbs
  return gulp.src('contents/page.hbs')
    .pipe(tap(function(file) {
      // file is page.hbs so generate template from file
      var template = Handlebars.compile(file.contents.toString());

      // now read all the pages from the pages directory
      return gulp.src('contents/pages/**.md')
        .pipe(tap(function(file) {
          // use path library to get file name
          var name = path.basename(file.path, ".md");
          // read meta data contents
          var contents = file.contents.toString();
          var index = contents.indexOf("---");
          // metadata found
          if (index !== -1) {
            var data = JSON.parse(contents.slice(0, index));
            // add name to meta data for lookup
            data.name = name;
            // add url to our meta data
            data.url = "/pages/" + file.relative.replace(".md", ".html");
            // save meta data into object outside stream
            Data.pages.push(data);
            // replace file contents without meta data
            contents = contents.slice(index+3, contents.length);
            file.contents = new Buffer(contents, "utf-8");
          }
        }))
        // convert from markdown
        .pipe(markdown())
        .pipe(tap(function(file) {
          var name = path.basename(file.path, ".html");
          // file is the converted HTML from the markdown
          // set the contents to the contents property on data
          var data = _.findWhere(Data.pages, { name: name });
          data.contents = file.contents.toString();
          // we will pass data to the Handlebars template to create the actual HTML to use
          var html = template(data);
          // replace the file contents with the new HTML created from the Handlebars template + data object that contains the HTML made from the markdown conversion
          file.contents = new Buffer(html, "utf-8");
        }))
        .pipe(gulp.dest('build/pages'));
    }));
});