Sample Gruntfile
'use strict';
// grunt is a module exporting a single function
module.exports = function (grunt) {
// shows detailed time information about tasks for optimizing build times
require('time-grunt')(grunt);
// automatically load tasks upon encountering them in the config, so .loadNpmTasks() methods are no longer necessary
require('jit-grunt')(grunt, {
useminPrepare: 'grunt-usemin' // custom tasks must be given explicitly
});
// configuration of all tasks
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'), // import external data to use dynamically
cfg: grunt.file.readJSON('config.json'), // e.g. <%= pkg.name %> or <%= cfg.url %>
// checks .js for syntax, consistency, best practices
jshint: {
options: {
jshintrc: '.jshintrc', // file containing rules to conform to
reporter: require('jshint-stylish') // optional module for reporting
},
all: { // sub-task name (in this case there's just one, thence 'all')
src: [ // array of source files to check
'Gruntfile.js',
'app/scripts/{,*/}*.js'
]
}
},
jscs: {
options: {
config: ".jscsrc"
},
src: "app/scripts/{,*/}*.js"
},
'string-replace': { // replace a string in a file
dist: { // sub-task name
files: {'dist/' : 'dist/index.html'}, // source files to check for pattern
options: {
replacements: [
{
pattern: 'bloody', // change this
replacement: 'BEEP' // to this
},
{
pattern: 'bugger',
replacement: 'BEEP'
}]
}
}
},
copy: { // copy files to another location
files: { // sub-task name
cwd: 'files', // base directory for the sub-task
src: '**', // relative path & pattern of source files
dest: 'dist/files', // destination
ext: 'bak', // replace existing extension; or
rename: function (dest, src) { // rename function with 2 optional parameters
return dest.replace('dev', 'backup '+src)+'/backup.txt'; // returning a string with the complete destination
},
expand: true // enable the preceding options
},
index: {
cwd: 'app',
src: ['*.html', '.htaccess'],
dest: 'dist',
expand: true
},
views: {
cwd: 'app',
src: 'views/**',
dest: 'dist',
expand: true
},
stat: {
cwd: 'app/static',
src: '**',
dest: 'dist',
expand: true
}
},
clean: { // deletes a folder to start new build
build:{ // sub-task name
src: ['dist/'] // source directory to be deleted
}
},
sass: {
dist: {
files: [{
expand: true,
cwd: 'app/styles',
src: ['main.scss'],
dest: 'dist/styles',
ext: '.css'
}]
}
},
// prepare files between tags like <!-- build:js ../dist/app.min.js --> or <!-- build:css ../dist/style/css --> and <!-- endbuild --> for other tasks
useminPrepare: { // configure usemin
html: 'app/index.html', // source html
options: {
dest: 'dist'
}
},
concat: { // concatenate files
options: {
separator: ';'
},
// dist configuration is provided by useminPrepare
dist: {}
},
uglify: {
// dist configuration is provided by useminPrepare
dist: {}
},
cssmin: {
dist: {}
},
// add a unique identifier to resource files to avoid loading resources cached by browser
filerev: {
options: {
encoding: 'utf8',
algorithm: 'md5',
length: 8
},
release: {
// filerev:release hashes(md5) all assets (images, js and css )
// in dist directory
files: [{
src: [
'dist/scripts/main.js',
'dist/styles/main.css',
]
}]
}
},
// change references for files prepared by useminPrepare
usemin: {
html: ['dist/*.html'], // destination folder for html
options: {
assetsDirs: ['dist', 'dist/styles']
}
},
watch: { // watch files for changes and run tasks
copy: {
files: [ 'app/*.html', 'app/views/**', 'app/static/{,*/}**'],
tasks: ['buildLocal']
},
scripts: { // sub-task name
files: ['app/scripts/{,*/}*.js'], // files watched
tasks:['buildLocal'] // tasks to run
},
styles: {
files: ['app/styles/*.css'],
tasks:['buildLocal']
}
}
});
grunt.loadNpmTasks('grunt-notify');
grunt.loadNpmTasks('grunt-string-replace');
/**********************************************/
// define a list of tasks to be run
grunt.registerTask('buildLocal', [
'jshint',
'jscs',
'clean',
'useminPrepare',
'concat',
'cssmin',
'uglify',
'copy',
'filerev',
'usemin'
]);
// other lists can be used as part of a list (e.g. remote build runs local build + censorship)
grunt.registerTask('buildRemote', [
'buildLocal',
'string-replace'
]);
// define default tasks to be run when calling 'grunt'
grunt.registerTask('default', [
'buildLocal'
]);
};