- Version 10.0.1
- Project Flyweb Production
- Section blog
- Tags
Published This Post is a few years old and the Information provided might be out of date!
Don't be afraid to Grunt
What the hell is "grunt" and why should i use it.
I keep reading about task runner "grunt" in my RSS feeds. So I finally sat down and took a deeper look on how to use it in my work flow. Grunt can
take repeating tasks from your hands and run them in the background e.g. minimize files on the fly.
Let's get Grunt running
First things first - before we get started using grunt we need to install Node. Head over to Node.js and follow the install instructions - http://nodejs.org/
You don't merely need to know Node.js, so don't worry about that. After Node is installed type the following command in your Terminal to install grunt.
See http://gruntjs.com/getting-started if you need a more in-deep help.
Install grunt-cli
globally with the following npm
command
$ npm install -g grunt-cli
To test if everything was correctly installed type grunt --version
into the terminal. This should display something similar.
$ grunt --version
grunt-cli v0.1.13
grunt v0.4.4
Ready to "grunt" at your Project
The next Step is to create two files in your Project Folder - package.json
and gruntfile.js
. You could also use the command npm init
to create the package.json
file.
1. package.json
This JSON File manages the installation and tracking of your development dependencies. Now anyone on your Team can have the same development environment if you all use the same package.json
file.
Type npm install grunt
into the terminal and npm
will download the dependency files and put them into the node_modules
folder. Also it will create the entry in the package.json
file. The flag --save-dev
will mark the package information as devDependencies
.
This is the package.json
from my flyweb Project:
{
"name": "flyweb",
"version": "0.1.0",
"homepage": "http://www.flyweb.at",
"author": {
"name": "Superfly",
"url": "http://www.flyweb.at"
},
"private": true,
"devDependencies": {
"grunt": "~0.4.1"
}
}
Note: When I first created this file I used another Version number and that caused some problems, so use "version": "0.1.0"
. For further Information regarding the package.json File see - https://www.npmjs.org/doc/json.html
2. Gruntfile.js
The file created gruntfile.js
is the place where to configure the all grunt
Plugins and Tasks.
module.exports = function(grunt){
grunt.initConfig({
pkg: grunt.file.readJSON('package.json')
});
grunt.registerTask('default', []);
};
This is the standard setup which actually doesn't do anything at this point. We first need to add any specific task or dependencies.
3. Install Dependencies/Plugins
There are two ways to install packages. First edit the package.json
file and add the package name and version number, then afterwards run npm install
. Or use the second option and let npm
do all the work with the following command. Let's install the grunt-contrib-cssmin
dependency which can help compress CSS files.
$ npm install grunt-contrib-cssmin --save-dev
The package.json
now look like this, grunt-contrib-cssmin
was added into the devDependencies
.
{
"name": "flyweb",
"version": "0.1.0",
"homepage": "http://www.flyweb.at",
"author": {
"name": "Superfly",
"url": "http://www.flyweb.at"
},
"private": true,
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-cssmin": "*"
}
}
See http://gruntjs.com/plugins for more Plugins. Now we add the grunt-contrib-cssmin
dependency to the gruntfile.js
.
module.exports = function(grunt){
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json')
});
grunt.registerTask('default', []);
};
To spare the trouble of adding each grunt-*
package by hand, you can use the package matchdep
- https://github.com/tkellen/js-matchdep.
$ npm install matchdep --save-dev
Afterwards you can just add matchdep
to your gruntfile
and all packages which start by the name grunt-*
will be added automatically.
module.exports = function(grunt){
// grunt.loadNpmTasks('grunt-contrib-cssmin');
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json')
});
grunt.registerTask('default', []);
};
Configure and Run Tasks
The next step is to configure grunt-contrib-cssmin to combine and minify all CSS files. We need to add the name of the package as Object key and configure it as we needed. Then we create a new Task with the name buildcss
and refer to the new package configuration which should be executed.
module.exports = function(grunt){
"use strict";
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
cssmin: {
combine: {
files: {
'app/css/flyweb.min.css' : [
'app/css/dev/normalize.min.css',
'app/css/dev/foundation.min.css',
'app/css/dev/prism.css',
'app/css/flyweb.min.css'
]
}
},
minify: {
src: 'app/css/flyweb.min.css',
dest: 'dist/css/flyweb.min.css'
}
}
});
grunt.registerTask('default', []);
grunt.registerTask('buildcss', ['cssmin']);
};
Start your grunt Tasks
To start the default
Task just type the plain grunt
command in your Terminal. But since we don't have any dependencies defined with the default
task it will do nothing. To start our newly created buildcss
Task we need to use the command:
$ grunt buildcss
You can name your Tasks whatever you want, mine is called buildcss
which runs the plugin cssmin
. Add as many Plugins as you need to your Task e.g.
grunt.registerTask('buildcss', ['cssmin', 'foo', 'bar']);
All the grunt belongs to me
It would be ridiculous to run the grunt
command by hand every time some CSS files changes. Instead wouldn't it be great to run the minify CSS Task every time you make changes to your CSS files? Install the grunt
package grunt-contrib-watch
- https://www.npmjs.org/package/grunt-contrib-watch - and configure it to achieve auto reloading for your Browser and to minify the CSS file on each file change.
module.exports = function(grunt){
"use strict";
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
cssmin: {
combine: {
files: {
'app/css/flyweb.min.css' : [
'app/css/dev/normalize.min.css',
'app/css/dev/foundation.min.css',
'app/css/dev/prism.css',
'app/css/flyweb.min.css'
]
}
},
minify: {
src: 'app/css/flyweb.min.css',
dest: 'dist/css/flyweb.min.css'
}
},
watch: {
css: {
files: ['app/css/dev/flyweb.css'],
tasks: ['buildcss'],
options: {
livereload: true
}
}
});
grunt.registerTask('default', []);
grunt.registerTask('buildcss', ['cssmin']);
grunt.registerTask('watch');
};
Head over to the Terminal and start the watch
Task with:
$ grunt watch:css
The watch
Task will start waiting for changes in the defined file/s. Each time it recognize a change the task buildcss
will be started. Isn't that nice? But it even gets better.
Livereload
I don't know how many million times I reloaded a browser to see the changes I've made. The grunt-contrib-watch
dependency also has the beloved livereload build-in. What now happens is the best part - edit the CSS files, get it minified on the fly and the browser reloads all on its own, yay!
There are two ways to get Livereload running after the installation in grunt.
- Install the Browser Plugin from livereload.com
- Or add the following HTML Snippet to your HTML code / template
<script src="http://192.168.0.1:35729/livereload.js?snipver=1"></script>
Note: If you use a local Network with you development Server use the second option.
From here to eternity
Head over to the grunt Homepage and see what Plugins are available. Check out concat_sourcemap
, uglify
, autoprefixer
and many more which make your Webdeveloper life much easier. This was just a little start to the things grunt can do, there is much more which can be done.
I found this two tutorials very useful to get started with grunt - http://24ways.org/2013/grunt-is-not-weird-and-hard/, http://www.smashingmagazine.com/2013/10/29/get-up-running-grunt/