I’ve been using Grunt for over 3 years now, almost all the way back since I started using CSS pre-processing. In the beginning I was using CodeKit, which is still an awesome tool. I prefer Grunt because I can code and commit my workflow into the repository of the project. There are some other technical benefits, but I encourage anyone starting out to buy a copy of CodeKit.
Most of my projects start out with some static HTML and some Sass and JavaScript that I need to write. This boilerplate Gruntfile.js is my starting point.
I have a bunch of prefixes that make keeping up with paths a lot quicker when going about editing and customizing the tasks.
I often use additional tasks, but these are the foundation of most of my work.
A lot of folks have been switching to Gulp lately. I hear one of the perks is speed. I found that once I broke up my watch task to watch Sass files and run Sass tasks then watch JavaScript files and run JavaScript tasks that things went a lot faster. Combine that with liveReload and I haven’t been motivated to switch … yet.
Notice the dev
task. I use Connect to serve the root of the repository on port 9001 while using watch
to compile when any changes happen. This is a great way to start coding right away on a real web server before I get into WordPress, Rails, Jekyll or whatever I’m building into.
module.exports = function(grunt) {
'use strict';
grunt.initConfig({
pkg: grunt.file.readJSON('package.json')
, coffeelint: {
app: ['./assets/javascripts/**/*.coffee']
}
, coffee: {
compile: {
options: {
sourceMap: true
}
, files: {
'./assets/javascripts/main.js': ['./assets/javascripts/_*.coffee']
}
}
}
, jshint: {
dist: {
src: [
'./Gruntfile.js'
]
, options: {
'strict': true
, 'node': true
, 'browser': true
, 'jquery': true
, 'onevar': true
, 'laxcomma': true
, 'laxbreak': true
, 'eqeqeq': true
, 'immed': true
, 'undef': true
, 'unused': true
, 'latedef': true
}
}
}
, uglify: {
dist: {
files: {
'./assets/javascripts/modernizr.min.js': ['./assets/javascripts/modernizr.js']
}
, options: {
sourceMap: true
}
}
, lib: {
files: {
'./assets/javascripts/lib.min.js': [
'./bower_components/jquery-hoverIntent/jquery.hoverIntent.js'
, './bower_components/imagesloaded/imagesloaded.pkgd.js'
, './bower_components/jquery-throttle-debounce/jquery.ba-throttle-debounce.js'
, './bower_components/decently-smart-target/jquery.dst.js'
]
}
, options: {
sourceMap: true
, mangle: false
}
}
}
, sass: {
dist: {
files: {
'./assets/stylesheets/main.css': './assets/stylesheets/main.sass'
}
, options: {
style: 'compressed'
}
}
}
, watch: {
coffee: {
files: [
'./assets/javascripts/*.coffee'
]
, tasks: ['coffeelint', 'coffee']
}
, js: {
files: [
'./Gruntfile.js'
, './assets/javascripts/*.js'
]
, tasks: ['jshint', 'uglify']
}
, sass: {
files: [
'./assets/stylesheets/**.sass'
, './assets/stylesheets/**.scss'
]
, tasks: [
'sass'
]
}
}
, connect: {
server: {
options: {
port: 9001
, base: '.'
, livereload: true
}
}
}
});
[ 'grunt-coffeelint'
, 'grunt-contrib-coffee'
, 'grunt-contrib-jshint'
, 'grunt-contrib-uglify'
, 'grunt-contrib-sass'
, 'grunt-contrib-watch'
, 'grunt-contrib-connect'
].forEach(function (task) {
grunt.loadNpmTasks(task);
});
grunt.registerTask('default', ['coffeelint', 'coffee', 'jshint', 'uglify', 'sass']);
grunt.registerTask('dev', ['connect', 'watch']);
};
[4]: gist 8885736