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
- Install Nodejs web server. This is only used for development tooling, not the target web server. (Use the installer or chocolatey)
- Install Grunt command line globally using npm
 npm install -g grunt-cli
Init project
- Go to the project root folder
- Create a package.json (npm configuration; containing at least name and version, plus probably devDependencies)
 Either manually ornpm initand follow prompts
 { "name": "staticvoid", "description": "static void website", "version": "1.0.0", "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-uglify": "~0.6.0", "grunt-contrib-cssmin": "^0.10.0" } }
- Create a gruntfile.js
 It's a node module (module.exports = function (grunt) { /*...*/ }
 There is a grunt-init plugin with various templates for new projects
- You can add grunt plugins (and grunt itself) to packages.json "devDependencies"
 Manually ornpm install grunt --save-dev(note the double -)
- Run grunt: grunt(runs the default task)
 Orgrunt build(if you have a build task)
The package.json and gruntfile.js is enough to tell npm/grunt what to do.
Gruntfile.js
The main sections
- grunt.initConfig({ /* configurations */ } );
 Configure each grunt task (if not using defaults)- Each config has optionsand arbitrary named targets (which can contain specificoptions)
- Specify grunt uglify:releaseto 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,
 
 } ]
 
- Destination: origin format. 
 
- Each config has 
- grunt.loadNpmTasks('task');
 Load the task. There is a neat task to reduce all those lines to this: require('load-grunt-tasks')(grunt);
- 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 '<%= %>
- via npm (npm install gruntTask --save-dev)
- in gruntfile.js configure it in initConfig
- loadNpmTasks
- 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.