Blog _

Automate CSS minification with Grunt


Posted at 1:07 pm on December 5, 2016 by Cesar

Have you ever been in a situation where you decide to view a website on your smart phone while on the go and end up abandoning it because it loads too slowly? I certainly have, and given that the percentage of  websites accessed via phone is steadily growing it highlights the importance of optimising your website for speed. According to this kissmetrics infographic you can expect 25% of you viewers to abondon you site after a 4 second loading time.

In this blog post I will walk you through the concatenatenation of multiple CSS files into one minified file using Grunt. Trust me, you’ll love grunt!

What is grunt?

Grunt is a Javascript task runner that allows you to automate processes that would otherwise become repetitive. For example, let say you want to look through all of your CSS files and make sure that all vendor prefixes are added where ever neccessary – theres a Grunt plugin to automate that!

Here, I will talk you through the process of automating CSS minification using Grunt. Hopefuly you will understand the power of grunt and use that as a starting point to go out and explore the numerous plugins available.

 

What is minification?

Minification is simply the removal of all uneccessary characters (characters that serve no functionality) from a piece of code in order to reduce it’s size and hence, its download time. Put simply, all the space and next line characters are there to make the code readable for humans, If we remove all the spaces, we can reduce the file size and the computer wont mind!

 

CSS minification with Grunt

-Step 1, Node.js

Node allows you run processes using Javascript on your machine – and Grunt runs on javascript.

The link above will talk you through the installation process, It’s all there so I wont repeat it here. Although it is important to note that in order to install Grunt, you will first have to install Node.js as Grunt as well as all it’s plugings are aquired using the node package manager (npm) which comes included in the Node installation.

-Step 2 Install the  Grunt Command Line Interface and Grunt using you Command Promp/ Terminal

The Node installation can be done using the installer, however, the easiest way to install grunt is to use the command prompt or Terminal (for mac users). This might seem scary to anyone who hasn’t used the command prompt before but……

Do not be alarmed – its very simple!

Open the command prompt (as administrator) and simply type the following

npm install -g grunt-cli

What is this doing?

npm install – references the node package manager, and tells it that you want to install something.

-g – This indicates that you want the installation to be at the global level. We add this so that you run the “grunt” command from anywhere (e.g. any directory).

grunt-cli – This is what we want to install on the system (the grunt command line interface).

Step 3  – Create a project.json file at the root directory of you project and install grunt locally.

Now that we have installed Node.js, as well as the grunt CLI,  we can now change directory of the command prompt to the root folder of our project. For example;

For me, I use Xampp as my local server on all of my projects and so I put all project folders within the xampp htdocs. If I type the following into my command prompt, it will change its directory to the location of my project files

cd C:\xampp\htdocs\example-site

Next type:

npm init

and you will be asked for the project details, such as its name – If you are asked anything you are unsure of just press enter. It is asking you for details so that it can populate certain details in the package.json file that it is automatically creating for you – but these can be changed at any time.

What is the purpose of the package.json file?

This file contains details about the project as well as listing what the project dependencies are, everytime you install a new plugin with grunt, it will automatically update the package.json file. This is what my package.json file looks like at the moment.

{
  "name": "example",
  "version": "1.0.0",
  "description": "example",
  "main": "index.html",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

As we install plugins they will be added to the json file under “devDependencies”. Incase you were wondering, json stands for JavaScript Object Notation – its a way of storing information that is designed to be easy and human readable. Information is organised in name/value pairs as we can see above.

After you create the package.json file you need to install grunt locally. so open your command prompt and change the directory to the root of your project folder and type

npm install grunt --save-dev

Step 4 – Install the minification plugin: grunt-contrib-cssmin

We are now ready to install the plugin that is going to minify our css file. Installing grunt plugins is extremely easy.

Side Note Hint: All plugins that contain “contrib” in the title are officially maintained and are marked with a star in the plugin download section, this means that you can pretty much bet that they will be stable and reliable.

To install the plugin, go to the command prompt and make sure that it is pointing to the root directory of your project. Then you simply type:

npm install grunt-contrib-cssmin --save-dev

And press enter.

The –save-dev ensures that the plugin is added to the “devDependencies” section of your package.json file.

If we now refer back to the package.json file, you will see that a “devDependencies” entry has appeared containing the cssmin plugin name.

{
  "name": "example",
  "version": "1.0.0",
  "description": "example",
  "main": "index.html",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "grunt-contrib-cssmin": "^1.0.2"
  }
}

Step 5 – Create and set up the gruntfile.js

The gruntfile.js is used to set up and configure the tasks that you want grunt to carry out, we also load the plugins in this file. Go to the root directory of the project and create a file called gruntfile.js.

I like to look at a gruntfile as containing 3 main parts 1)task configuration, 2) plugin loading, 3)registering tasks.

This is what my gruntfile.js looks like:

module.exports = function(grunt) {
		
	//configure tasks
	grunt.initConfig({
				
		pkg: grunt.file.readJSON('package.json'),
		
		cssmin : {
		   combine: {
				files: {
				   'output.min.css': ['css/*.css']
				}  
			}

		}
		 
	});
		
	//Load Plugin
	grunt.loadNpmTasks('grunt-contrib-cssmin');
		
	//Register Task
	grunt.registerTask('default', 'cssmin');

};
Gruntfile features

1) everything goes inside a function….

  module.export = function(grunt){
     //Code goes Here!
}

2) Task configuration happens inside a…

   grunt.initConfig({

   });

First we reference the packages.json file, and then configure our plugins (In this example cssmin)

   grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),

      cssmin : {
	    combine: {
			files: {
				   'output.min.css': ['css/*.css']
				}  
			}

		}
   });

Here we are using cssmin to combine all CSS files contained within the css folder and create a file
called “output.min.css” which will be located in the root – i.e. at the same location that the gruntfile.js is.

“output.min.css” will be a minified version of all the .css files that are withing the css folder.

This means that you can choose to use as many seperate css files as you please in the production stage of your project, and as long as you run grunt before deployment and reference the output file only – you will have a concatenated and minified single CSS file for all of your styles.

3)Load the plugin
The cssmin plugin in my example is loaded as follows:

   grunt.loadNpmTasks('grunt-contrib-cssmin');

Any additional plugin is added in the same fashion, just add it underneath, for example:

   grunt.loadNpmTasks('grunt-contrib-cssmin');
   grunt.loadNpmTasks('grunt-contrib-uglify');
   // ect.....

4)Register Task
It is possible to set up grunt to run any combinations of plugins you choose.

   grunt.registerTask('default', 'cssmin');

In the example above, we are instructing grunt to run the cssmin plugin as the default task. This means that when you run grunt from your command prompt by typing “grunt” at the root of your project directory, it will run cssmin. Lets say you wanted minified CSS in the production version but during development you didnt want it to run the cssmin plugin. Then you could create a second task called “dev” (you can use any name you want) and then run other plugins but omit the cssmin.

    grunt.registerTask('dev', 'other plugins');

..and then run it by typing “grunt dev” in your command prompt.
You can create as many tasks as you please.

 

 

Step 6 Using grunt-contrib-watch To watch and update your minified file automatically whenever changes are made

Now that we have cssmin installed and grunt set up, we can use the grunt-contrib-watch plugin to watch our css files and run cssmin whenever any changes are made to the original CSS files – automatically!

First install the plugin by opening your command prompt and changing the directory to the root folder of your project and entering the following:

   npm install grunt-contrib-watch --save-dev

Then open your gruntfile.js and, in the task configuration section under cssmin, configure the plugin to watch over all your css files and instruct it on which plugin to run whenever there are changes.

   watch: {
	css: {
		files: ['css/*.css'],
		tasks: ['cssmin']
	     }
		
	},

Next, load the plugin in the plugin loading section of your gruntfile.js

   grunt.loadNpmTasks('grunt-contrib-watch');

Finally, encase the “cssmin” in the registered task in square brackets [].

   grunt.registerTask('default', ['cssmin']);

And your done!!

If you have been following along your gruntfile.js should now look like this:

   module.exports = function(grunt) {
		
	//configure tasks
	grunt.initConfig({
				
		pkg: grunt.file.readJSON('package.json'),
		
		cssmin : {
		   combine: {
				files: {
				   'output.min.css': ['css/*.css']
				}  
			}

		},
		
		watch: {
			css: {
				files: ['css/*.css'],
				tasks: ['cssmin']
			}
		},
		 
	});
		
	//Load Plugin
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-contrib-cssmin');
		
	//Register Task
	grunt.registerTask('default', ['cssmin']);

};

now all you have to do is type “grunt watch” in your command prompt and hit enter, and grunt will watch your css files for any changes, and update the minified file accordingly

I have created a git repository with a working example of the things covered in the article.
All you have to do is go to https://github.com/rizo1/grunt-example-1and download the files. Then open your command prompt and change the directory the root – i.e. where index.html can be found, and finally, type “npm update” to automatically install the grunt plugins. (assuming that you have nodejs and grunt-cli installed globally). You should then be able to run the “grunt” and “grunt watch” commands.

Congratulations, you can now use Grunt – there are literally thousands of plugins to choose from, so explore.
Maybe you would like me to do a step-by-step video?
Did you found this helpful?
Either way, let me know in the comments below!



Comments

  • It never works. I keep getting “Fatal error: Unable to find local grunt.” no matter how correctly I followed the steps here.

    • Hi Jacob,
      I’m currently a bit busy, but I will try to make a gulp version in the comming
      months. Thanks for the feedback!

  • this was really helpful, thank you.
    I’ve used grunt before, but frankly, I had never even tried to set it up myself.
    Something that is bugging me though…. I have a single css file that has to be minified, and when i run the watch task and change the file, the task will run 5times for some reasons… Which means it recreates the min.css file 5 times, even if there was just a slight change. Any ideas why that happens? My gruntfile.js looks mostly exactly like yours….

    • Hi Stef,
      Nice site!
      Whats going on is that when you run “grunt watch” and make an edit to your CSS file,
      It continually processes the same files in an infinite loop because the read and the
      write directory are pointing to the same location – opps! my mistake.
      Usually unprocessed files are run through grunt and sent through to a different
      folder and this would not happen.

      I have created a git repo with an amended example where the concatenated and
      minified css is sent to the root directory instead.
      download the files from https://github.com/rizo1/grunt-example-1 and in your command prompt change the directory to the root (where index.html is located)
      and type “npm update“.
      Once the update is complete, you should be able to run “grunt” and test out “grunt watch”.

      And in the meantime I will update the blog post!
      Let me know how you get on, or if you need further assistance.

      Cesar

      • Uaa thanks for the quick answer! Worked like a charm!
        I figured it must be something like that, but wasn’t quite sure which path I had to change.
        Thanks <3

  • Write a Reply or Comment

    Your email address will not be published. Required fields are marked *