In a previous post in this series, I walked you through setting up Grunt in your project. Now that we have everything setup, I would like to talk about a few advanced techniques that you can use with Grunt.
Specifically, I'm going to focus on the configuration of your existing tasks and how to create custom tasks.
Configuration
Every project is unique and the way you will configure your Gruntfile.js will be completely different from, say, how someone else may configure there own. Of course, Grunt is ready to handle however you want to configure each task.
Nesting
A great feature of Grunt is that you can nest your configurations for each plugin. There could be a number of reasons that you want to do this like changing the options for specific files, or maybe you want to separate out files for your watch task.
In order to do this, you will simply create multiple objects inside of the Grunt plugin object. A common use case would be creating multiple files for your theme, both theme and admin. Let's use this example to uglify the theme's JavaScript files when they change, and then uglify the dashboard's JavaScript files when they change.
Don't forget to add the plugin into your project:
grunt.loadNpmTasks('grunt-contrib-uglify');
Then we can set up the configuration for our uglify process:
uglify: { theme: { options: { beautify: false, mangle: true }, files: { 'js/theme.main.min.js': 'js/dev/theme.*.js' } }, admin: { options: { beautify: true, mangle: false }, files: { 'js/admin.min.js': 'js/dev/admin.*.js' } } }
And now we will configure our watch task to kick off specific tasks when different files are changed:
watch: { theme_js: { files: 'js/dev/theme.*.js', tasks: 'uglify:theme' }, admin_js: { files: 'js/dev/admin.*.js', tasks: 'uglify:admin' } }
Now when you kick off your watch, it will only kick off the appropriate uglify configuration based on the file that was changed. You can also kick off the Grunt task yourself by typing in either grunt uglify:theme
or grunt uglify:admin
from the command line.
Using package.json
Sometimes your tasks need to access something from your package.json file like the name, version, author, homepage, and so on. You see this a lot with the banner that is added at the beginning of a compiled JavaScript or CSS file. I also have used it in conjunction with the grunt-contrib-compress plugin.
In order to read the elements in the package.json file, you need to add the following inside your initConfig function so the tasks can read it like so:
grunt.initConfig({ pkg: grunt.file.readJSON('package.json') )}
Now that you have that line of code in there, you can access different elements like this:
<%= pkg.name %>
<%= pkg.version %>
<%= pkg.author %>
There's a great example of this inside the Bootstrap Gruntfile. You can see that they are using a number of elements in the package.json file in their banner object they are building.
banner: '/*!\n' + ' * Bootstrap v<%= pkg.version %> (<%= pkg.homepage %>)\n' + ' * Copyright 2011-<%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' + ' * Licensed under <%= pkg.license.type %> (<%= pkg.license.url %>)\n' + ' */\n',
Load Grunt Tasks
I also mentioned making sure to load all of your grunt tasks before executing them. This can make it a bit teadious if you find yourself adding and removing plugins often. If you don't want to worry about this, there's a great plugin you can use called load-grunt-tasks.
It would essentially change this:
grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-sass'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-compress'); grunt.loadNpmTasks('grunt-contrib-watch');
To this:
require('load-grunt-tasks')(grunt);
There is also some other great things you can do with this plugin as well to clean up your Gruntfile. I won't go into much detail since there's already a great post on how to do this.
Custom Tasks
Anoter great way to customize your grunt file is to create custom tasks. I'm going to share with you the three that I usually add to a project.
Default
It is suggested to use the default task in your project. This is essentially what you want to happen when you simply type in grunt
into the command line. It depends on your project, but a lot of times I find myself wanting to kick off the watch task by default.
Here's how you would do that:
grunt.registerTask('default', ['watch']);
You can choose whatever tasks you want to run by simply comma separating them. Let's say you wanted to run uglify then watch, here's how to do that:
grunt.registerTask('default', ['uglify, watch']);
Something to note when having multiple tasks: They will run in the order you specify. If one task fails, it will kill the process at that point of execution and will not run the rest of the tasks that you have defined.
Dist
Another task that I usually setup is one for distribution. Let's say that I am done with development for a release and want to prepare my project for distribution.
For this example, I have a number of tasks that I want to run for both my JavaScript and SASS files.
For my JavaScript files, I will use JSLint to check my syntax, concatenate a number of them into a single file, then I'll uglify the final file. Next, I will run a compile for all of my SASS files. Lastly, I will run copy to move all the files in their appropriate location and then compress the project into a .zip file so someone can install it via the WordPress dashboard.
Here's an example:
grunt.registerTask('dist', ['jslint, concat, uglify, sass, copy, compress']);
Conclusion
You should now have an idea of some more advanced Grunt techniques for your project. There are quite a bit more techniques that you will discover as you spend time with Grunt.
This concludes the series on using Grunt with your WordPress project. We talked about what Grunt is, reasons to use it, set it up in your project, and covered some advanced techniques. Grunt is continuing to gain popularity along with other front end technologies. I hope this is just the start of your experimentation with Grunt and other tools like it.
Comments