Vincent Chan
Vincent Chan

Reputation: 31

Configuring Grunt for Jekyll, Haml, Sass on GitHub Pages

I'm trying to run my development/prototyping environment (not a blog) using Jekyll, Haml, Sass and host it on GitHub Pages.

Locally, I use Grunt.js to compile HAML, SASS and serve/build Jekyll.

While my Gruntfile.js is able to do my tasks, it's extremely slow as I try to run the build and serve concurrently.

Any Grunt experts can point me to the right direction on how to optimize my Grunt config so it can run faster? Thanks!

Below is my current config:

grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),

jekyll: {
  options: {                          
    src : './',
    dest: './_gh_pages',
    config: '_config.build.yml'       // avoid the relative baseurl issue
  },

  serve: {
    options: {
      serve: true,
      port: 9001
    }
  },

  dev: {

  }
},

compass: {
  dev: {
    options: {
      config: 'config.rb',
      force: true
    }
  }
},

haml: {
  includes: {
    expand: true,
    cwd: 'haml/includes/',
    src: ['*.haml'],
    dest: '_includes/',
    ext: '.html'
  },
  layouts: {
    expand: true,
    cwd: 'haml/layouts/',
    src: ['*.haml'],
    dest: '_layouts/',
    ext: '.html'
  },
  pages: {
    expand: true,
    cwd: 'haml/',
    src: ['*.haml'],
    dest: './',
    ext: '.html'
  }
},    

watch: {
  options: {
    atBegin: true
  },
  sass: {
    files: ['sass/**/*.scss'],
    tasks: ['compass:dev']
  },
  haml: {
    files: ['haml/**/*.haml'],
    tasks: ['haml:includes', 'haml:layouts', 'haml:pages']
  },
  jekyll: {
    files: ['./**/*.html', './**/*.css'],
    tasks: ['jekyll:dev']
  }
},
concurrent: {
  target: {
    tasks: ['jekyll:serve', 'watch'],
    options: {
      logConcurrentOutput: true
    }
  }
}
});

grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-html-validation');
grunt.loadNpmTasks('grunt-jekyll');
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.loadNpmTasks('grunt-contrib-haml');
grunt.loadNpmTasks('grunt-concurrent');

grunt.registerTask('default', ['concurrent:target']);

Upvotes: 2

Views: 3214

Answers (1)

Wallace Sidhrée
Wallace Sidhrée

Reputation: 11597

I haven’t used Grunt with haml or jekyll, but I use it on a daily basis to manage several projects, using different packages as needed.

It’s hard to tell how complex or how big your application is just by looking at your Gruntfile.js, but I would definitely start by making tasks a bit smarter. The watch task is usually the one I put most attention on, because that’s preferably the only task that should run upon saving files. For instance if you save a .scss file, only the compass:dev task is fired up. If you save a .js file, the tasks jshint, jasmine and uglify:dev would fire up. That keeps the development wheel turning only where it’s needed, and Grunt completing tasks faster.

Another thing I don’t see in your Gruntfile.js is dedicated tasks for dev and dist, which can be a good practice. An example:

// Start web server
grunt.registerTask('serve', [
    'connect:livereload',
    'watch'
]);

// Compile production files
grunt.registerTask('dist', [
    'jshint',
    'jasmine',
    'uglify:dist',
    'compass:dist'
]);

// Compile developer friendly environment
grunt.registerTask('dev', [
    'jshint',
    'jasmine',
    'uglify:dev',
    'compass:dev',
    'connect:livereload'
]);

// Default task(s).
grunt.registerTask('default', 'dev’);

Use $ grunt serve on one shell to start a local server and watch the app. To make full builds without relying on the watch task, run $ grunt to make a full dev build (because that’s the default task on this example) or run $ grunt dist to make a production-ready build.

So my advice is to rely on the watch task while developing, and running do-it-all tasks sparingly. Grunt’s beauty is not only on multi-tasking, but also on tasking-on-demand. Running full builds on each and every file save is possible, but is not efficient.

BTW, your jekyll task within watch is empty, because jekyll:dev is empty:

jekyll: {
    files: ['./**/*.html', './**/*.css'],
    tasks: ['jekyll:dev']
}

Hope it helps!

Upvotes: 4

Related Questions