|
| 1 | +# Introduction to grunt.js |
| 2 | + |
| 3 | +Grunt is a tool for managing the javascript, css, and html files of your web project. Grunt is a task manager similar to Ruby's `rake`. You can run any arbitrary tasks you want, and there are a number of grunt plugins that make it easy to set up common tasks. Grunt is useful for running tests or for build steps, including turning sass, stylus, or less files into css, concatenating files, or creating .zip or .tar.gz packages of your project. |
| 4 | + |
| 5 | +### Outline of the steps in this tutorial: |
| 6 | + |
| 7 | +- Install node. |
| 8 | +- Install grunt-cli. |
| 9 | +- Setup project. |
| 10 | +- Set up package.json. |
| 11 | +- Create Gruntfile.js. |
| 12 | +- Run grunt tasks. |
| 13 | +- Make an awesome project. |
| 14 | + |
| 15 | +### Install node: |
| 16 | + |
| 17 | +You should already have Node.js installed from chapter 4, "In-depth with Node.js". If not, backtrack to that chapter for a guide to installing Node. |
| 18 | + |
| 19 | +### Install grunt-cli |
| 20 | + |
| 21 | +Installing node gives us the node package manager `npm`. We'll use it to install grunt-cli, which is the command-line tool that is used to run grunt tasks. |
| 22 | + |
| 23 | +**Run this in your terminal after installing node.js:** |
| 24 | + |
| 25 | +~~~~~~~~ |
| 26 | +npm intall -g grunt-cli |
| 27 | +~~~~~~~~ |
| 28 | + |
| 29 | +This installs the grunt command-line tool globally on your machine. Now you can run the `grunt `command! |
| 30 | + |
| 31 | +And, it won't do anything. |
| 32 | + |
| 33 | +Bummer. **But it will give you a message like this**: |
| 34 | + |
| 35 | +~~~~~~~~ |
| 36 | +grunt-cli: The grunt command line interface. (v0.1.6) |
| 37 | + Fatal error: Unable to find local grunt. |
| 38 | + If you're seeing this message, either a Gruntfile wasn't found or grunt hasn't been installed locally to your project. For more information about installing and configuring grunt, please see the Getting Started guide: [http://gruntjs.com/getting-started](http://gruntjs.com/getting-started) |
| 39 | +~~~~~~~~ |
| 40 | + |
| 41 | +The grunt command looks for a locally installed version of grunt, which you can include in your project as a development dependency in a package.json file. |
| 42 | + |
| 43 | +### Hey, package.json files are cool. |
| 44 | + |
| 45 | +You can use a package.json file for a lot of useful purposes. Primarily, it's used to list your project's dependencies on npm packages, as well as list the name, description, version, and source repository of the project. You can specify the type of license, version of node the project requires, the project's contributors, and more. Check out [this interactive package.json cheatsheet][http://package.json.nodejitsu.com/] for a nice rundown on the basics. |
| 46 | + |
| 47 | +So, our package.json will specify some development dependencies. |
| 48 | + |
| 49 | +**Some basic requirements:** |
| 50 | + |
| 51 | +- We'll test the javascript with qunit. |
| 52 | +- We'll write scss and compile it to css, then minify the css. |
| 53 | +- We'll concatenate and uglify our javascript files. |
| 54 | +- We'll use the `grunt watch` command to automatically run grunt tasks when files are edited. |
| 55 | +- We'll want a little http server to check out our game as we're developing it. |
| 56 | + |
| 57 | +Some of the above requirements could be perceived as excessive, but they help make this a meaty and useful tutorial, so deal with it. |
| 58 | + |
| 59 | +**So, we'll need to use some grunt plugins. We'll use these ones:** |
| 60 | + |
| 61 | +- [grunt-contrib-qunit][https://github.com/gruntjs/grunt-contrib-qunit] |
| 62 | +- [grunt-contrib-jshint][https://github.com/gruntjs/grunt-contrib-jshint] |
| 63 | +- [grunt-contrib-connect][https://github.com/gruntjs/grunt-contrib-connect] |
| 64 | +- [grunt-contrib-watch][https://github.com/gruntjs/grunt-contrib-watch] |
| 65 | + |
| 66 | + |
| 67 | +**That means our package.json file will look like this:** |
| 68 | + |
| 69 | +~~~~~~~~ |
| 70 | +{ |
| 71 | + "name": "your-project-name", |
| 72 | + "version": "0.0.1", |
| 73 | + "author": "Super Big Tree <[email protected]>", |
| 74 | + "description": "A silly game.", |
| 75 | + "repository": { |
| 76 | + "type": "git", |
| 77 | + "url": "https://github.com/your-profile/your-project-name.git" |
| 78 | + }, |
| 79 | + "devDependencies": { |
| 80 | + "grunt": "~0.4.0", |
| 81 | + "grunt-contrib-qunit": "~0.2.0", |
| 82 | + "grunt-contrib-jshint": "~0.1.1", |
| 83 | + "grunt-contrib-connect": "~0.1.2", |
| 84 | + "grunt-contrib-watch": "~0.4.4" |
| 85 | +}, |
| 86 | + "license": "MIT", |
| 87 | + "engines": { |
| 88 | + "node": ">=0.8" |
| 89 | + } |
| 90 | +} |
| 91 | +~~~~~~~~ |
| 92 | + |
| 93 | +**Go to your terminal. Create a folder that you want to serve as the project's folder:** |
| 94 | + |
| 95 | +~~~~~~~~ |
| 96 | +cd wherever/you/want/the/project/to/live |
| 97 | +mkdir your-project-name |
| 98 | +cd your-project-name |
| 99 | +~~~~~~~~ |
| 100 | + |
| 101 | +Now, create your package.json file: |
| 102 | + |
| 103 | +~~~~~~~~ |
| 104 | +touch package.json |
| 105 | +~~~~~~~~ |
| 106 | + |
| 107 | +Copy and paste the above package.json example into your package.json file using your favorite text editor. Save the file. **Now, you can run |
| 108 | +this:** |
| 109 | + |
| 110 | +~~~~~~~~ |
| 111 | +npm install |
| 112 | +~~~~~~~~ |
| 113 | + |
| 114 | +to install all the dependencies. |
| 115 | + |
| 116 | +If you run the command and get an error like this at the end, then something is not ok: |
| 117 | + |
| 118 | +~~~~~~~~ |
| 119 | +npm ERR! not ok code 0 |
| 120 | +~~~~~~~~ |
| 121 | + |
| 122 | +There's an error of some kind that will need to be worked out. For me, typically the problem is that I messed up the syntax or put the wrong version number for a dependency, so check things like that first. |
| 123 | + |
| 124 | +### Project setup: |
| 125 | + |
| 126 | +Let's make all our files and folders now! |
| 127 | + |
| 128 | +**This will make all the folders we want:** |
| 129 | + |
| 130 | +~~~~~~~~ |
| 131 | +> mkdir -p test js css/scss img |
| 132 | +~~~~~~~~ |
| 133 | + |
| 134 | +**This will make the files we want:** |
| 135 | + |
| 136 | +~~~~~~~~ |
| 137 | +touch js/player.js js/game.js js/enemies.js js/ui.js \ |
| 138 | +touch css/scss/main.scss css/scss/reset.scss css/scss/ui.scss \ |
| 139 | +touch test/player.js test/enemies.js test/game.js test/ui.js |
| 140 | +~~~~~~~~ |
| 141 | + |
| 142 | +Cool. Did that. **Now we make the Gruntfile:** |
| 143 | + |
| 144 | +~~~~~~~~ |
| 145 | +touch Gruntfile.js |
| 146 | +~~~~~~~~ |
| 147 | + |
| 148 | +**Open Gruntfile.js in your favorite editor and paste in this:** |
| 149 | + |
| 150 | +~~~~~~~~ |
| 151 | +module.exports = function(grunt) { |
| 152 | + grunt.initConfig({ |
| 153 | + // and here we do some cool stuff |
| 154 | + }); |
| 155 | +}; |
| 156 | +~~~~~~~~ |
| 157 | + |
| 158 | +The above code is the required wrapper code to make a Gruntfile work. Now, remember our package.json file. Buds, we can use the values from that file in our Gruntfile. |
| 159 | + |
| 160 | +**Check it out: **Let's say we're making a javascript library and want to put stuff like the name, version, author, source repository, and license of the project in a multi-line comment at the top of the file. It would be a bummer to have to edit that by hand every time the file is compiled for a new release. Instead, we can use values from package.json in our Gruntfile! |
| 161 | + |
| 162 | +First step is to read the contents of package.json by **putting this line in Gruntfile.js**: |
| 163 | + |
| 164 | +~~~~~~~~ |
| 165 | +pkg: grunt.file.readJSON('package.json'); |
| 166 | +~~~~~~~~ |
| 167 | + |
| 168 | +A package.json file is just JSON, right? Yeah, so it's easy to get at the values to do cool stuff. |
| 169 | + |
| 170 | +For fun, let's see what it takes to run a custom task inside a Gruntfile, and have it log some attributes from the package.json file. Alright? OK. |
| 171 | + |
| 172 | +This is a really simple task that logs the package name and version to the console, shown here as the complete Gruntfile.js: |
| 173 | + |
| 174 | +~~~~~~~~ |
| 175 | +module.exports = function(grunt) { |
| 176 | + grunt.initConfig({ |
| 177 | + // read the json file |
| 178 | + pkg: grunt.file.readJSON('package.json'), |
| 179 | +
|
| 180 | + log: { |
| 181 | + // this is the name of the project in package.json |
| 182 | + name: '<%= pkg.name %>', |
| 183 | +
|
| 184 | + // the version of the project in package.json |
| 185 | + version: '<%= pkg.version %>' |
| 186 | + } |
| 187 | + }); |
| 188 | +
|
| 189 | + grunt.registerMultiTask('log', 'Log project details.', function() { |
| 190 | + // because this uses the registerMultiTask function it runs grunt.log.writeln() |
| 191 | + // for each attribute in the above log: {} object |
| 192 | + grunt.log.writeln(this.target + ': ' + this.data); |
| 193 | + }); |
| 194 | +}; |
| 195 | +~~~~~~~~ |
| 196 | + |
| 197 | +**You can now run your task on the command line!:** |
| 198 | + |
| 199 | +~~~~~~~~ |
| 200 | +grunt log |
| 201 | +~~~~~~~~ |
| 202 | + |
| 203 | + |
| 204 | +**You should get output like this:** |
| 205 | + |
| 206 | +~~~~~~~~ |
| 207 | +Running 'log:name' (log) task |
| 208 | +name: your-project-name |
| 209 | +Running 'log:version' (log) task |
| 210 | +version: 0.0.1 |
| 211 | +Done, without errors. |
| 212 | +~~~~~~~~ |
| 213 | + |
| 214 | +If you didn't get output like that, check your Gruntfile for typos. If you did get output like that: Awesome! So we've made it pretty far. We've set up a project with a bunch of files and folders, created a package.json file with a list of devDependencies, installed the dependencies, and tried out a simple Gruntfile for running arbitrary tasks. |
| 215 | + |
| 216 | +If this seems like a lot, like it's beating up your brain, don't worry. After a few times of starting a project like this, these initial steps will get faster and easier. Heck, you might even create some kind of base project that you can build on with each new project so that you don't have to write the boilerplate every time. Or you could use a project like yeoman for its code generators. That's up to you, but when first learning this it's a reasonable idea to start from scratch and see how everything works. |
0 commit comments