static void

Grunt

Grunt is development tooling to run tasks on (client-side) websites for publishing. Tasks include pre-processing (coffee, less/sass), copying files, bundling and minifying css and javacript.

NB: another popular alternative to Grunt is Gulp (npm install --global gulp)

Bower is a package manager for client side assets (javascript, css, images). You can bower install jquery --save and bower update jquery.

Yeoman ("yo") is a website generator. It uses grunt and bower.

Installation

Init project

Don't commit node_modules to source control.
The package.json and gruntfile.js is enough to tell npm/grunt what to do.

Gruntfile.js

The main sections

  1. grunt.initConfig({ /* configurations */ } );
    Configure each grunt task (if not using defaults)
    • Each config has options and arbitrary named targets (which can contain specific options)
    • Specify grunt uglify:release to run a specific uglify: { release: {...}}
    • Otherwise all targets are executed when you run grunt uglify
    • Normally there's a files:. You can use globbing (eg *.js, /**/*.js).
      • Destination: origin format. files: { 'new.css': [ 'orig.css']}
      • Arrays format: files: [ {src: ['orig.css'], dest: ['new.css']}, ]
      • Dynamic expansion format: files: [ { expand:true,
        src: ['**/*.js'],
        dest: dist,

        } ]
  2. grunt.loadNpmTasks('task');
    Load the task. There is a neat task to reduce all those lines to this: require('load-grunt-tasks')(grunt);
  3. grunt.registerTask('default', ['uglify', 'cssmin']);
    Create the default task, plus others (commonly, 'build', 'test')

Most of the code is in grunt.initConfig. The naming convention is that a plugin task name matches between the sections (minus grunt- or grunt-contrib- prefixes). You can add variables at the top and refer to them as '<%= %>

Remember you have to add a task
  1. via npm (npm install gruntTask --save-dev)
  2. in gruntfile.js configure it in initConfig
  3. loadNpmTasks
  4. include it in your registerTask

Minify

This is a simple gruntfile.js which just minifies javascript and css
(First do npm install grunt-contrib-uglify --save-dev and npm install grunt-contrib-cssmin --save-dev

module.exports = function (grunt) {
    'use strict';

    //configure
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		//a banner stamp, using the package we just loaded
		banner: '/* <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n',
		
		uglify: {
		  options: {
			banner: '<%= banner %>'
		  },
		  dist: {
			files: {
			  'utilities.min.js': ['utilities.js']
			}
		  }
		},
		
		cssmin: {
		  css: {
			files: {
				'style.min.css': ['style.css']
			}
		  }
		}
	});
	
	//load tasks
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-cssmin');
	
	//create default task
	grunt.registerTask('default', ['uglify', 'cssmin']);
};

You can also minify html using npm install grunt-contrib-htmlmin --save-dev

module.exports = function (grunt) {
    'use strict';
	grunt.initConfig({
		htmlmin: {
			target: {
				options: {
					removeComments: true,
					collapseWhitespace: true
				  },
				  files: {
				   'index-min.html': 'index.html',
				  },
			}
		}
	});
	grunt.loadNpmTasks('grunt-contrib-htmlmin');
	grunt.registerTask('default', ['htmlmin']);
};

There's also an imagemin for images, and you can use it with MozJpeg to optimize jpegs for the web (like Facebook does).

Bundling

grunt-contrib-concat concatenates files together (for bundling). Use with uglify and cssmin like this:

module.exports = function (grunt) {
    'use strict';

	grunt.initConfig({
		concat: {
			js: {
				options: {
					separator: ';',
					sourceMap: true,
				},
				//the !filename excludes a file (it's the destination)
				src: ['mu*.js', '!mu_all.js'],
				dest: 'mu_all.js',
			},
			css: {
				src: ['style*.css', '!style_all.css'],
				dest: 'style_all.css',
			}
		},
		uglify: {
		  js: {
			files: {
			  'mu_all.js': ['mu_all.js']
			}
		  }
		},
		
		cssmin: {
		  css: {
			files: {
				'style_all.css': ['style_all.css']
			}
		  }
		},

	});
	
	grunt.loadNpmTasks('grunt-contrib-concat');
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-cssmin');
	
	grunt.registerTask('default', ['concat', 'uglify', 'cssmin']);
};

The problem is your html still loads the individual files. Either use grunt-string-replace or grunt-usemin to fix the individual script and link tags (html comments find the replaceable blocks).

Preview in website

grunt-contrib-connect opens a static website.

module.exports = function (grunt) {
    'use strict';
	grunt.initConfig({
		connect: {
			server: {
				options: {
					port: 9001, //use this port
					hostname: '127.0.0.1', //localhost
					//base: 'www-root', //base directory
					open: true, //open in browser
					keepalive: true, //keep it alive (until ctrl/c grunt)
				}
			},
		}
	});
	grunt.loadNpmTasks('grunt-contrib-connect');
	grunt.registerTask('default', ['connect']);
};

Clean and copy

grunt-contrib-clean deletes files and folders, grunt-contrib-copy copies them.

Typically your root will contain an app (development) folder and dest (destination) folder. These tasks copy everything over.

module.exports = function (grunt) {
    'use strict';
	grunt.initConfig({
		clean: {
			target: [ 'dist/**/*' ], //all files and subfolders in dist
		},
		copy: {
			target: {
				options: {
					timestamp: true //preserve timestamp
				  },
				  files: [
					{
						expand:true,
						src: 'net/**', //** is files and directories
						dest: 'dist', //to dist/net/...
					}
				  ],
			}
		}
	});
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-contrib-copy');
	grunt.registerTask('default', ['clean', 'copy']);
};

Others

grunt-contrib-watch is a filesystem watcher which launches a task (e.g. build) whenever specified files change.

grunt-angular-templates concats and minifies all the angular templates into $templateCache. Then you can concat into a single app.js.