onsa
12/17/2016 - 12:45 AM

Sample Gruntfile

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'
	]);
};