Preface
Special Note: If you feel this article is not detailed enough, strongly recommend reading the tutorial on Grunt Official English Website, because the Chinese version partially translated the comments, which is worse than not translating (easy to be misled by translation)
- What is Grunt?
Grunt is an automatic build tool, similar things include Ant, Buildy, Gmake, etc. For more information please see [AnYuQingYang: JS Automation](/articles/js 自动化/)
- What is Grunt used for?
Automatic build tools can integrate automation tools together, managed in the form of tasks, so Grunt official website's subtitle is The JavaScript Task Runner.
Simply explained, building projects -> modular development -> reuse -> testing -> debugging -> verification -> release -> version control, this entire process requires many automation tools, such as Require, QUnit, JSHint, Uglify, etc. Almost every source code modification requires manually running certain tools in specific order again...
With automatic build tools like Grunt, you can simplify the run again operations. After writing the configuration file, just run custom tasks via command line. You can even cooperate with grunt-contrib-watch plugin to listen for file modifications and automatically run tasks
- What's good about Grunt?
-
Popular: Twitter, JQuery, Adobe, Mozilla, etc. all use Grunt
-
Many plugins: Currently (2015.5.22) there are already 4560 Grunt plugins, including commonly used JSHint, Require, Sass, etc., more than enough. If really not enough, you can write plugins yourself
-
Easy to use: Configuration files are relatively simple, plugin documentation is complete (npm official website provides unified management)
I. Installing Grunt
- Install NodeJS
Windows users just go to http://nodejs.org/ to download and install the package, comes with npm
Installation tutorial for other platforms
After installation, type node -v in command line to test
- Install npm
Type npm -v in command line to test. If error occurs, figure out how to install npm yourself
- Install Grunt-CLI (Command Line Interface)
Type npm install -g grunt-cli in command line and wait for installation to complete
II. Configuration Files
Need two configuration files:
-
package.json: Used for Nodejs package management, declares project dependent modules (grunt and grunt plugins)
-
Gruntfile.js: Grunt configuration file, used to define tasks, can be named Gruntfile.js or Gruntfile.coffee
Note: Both package.json and Gruntfile.js must be placed in the project root directory, submitted together with project source code
To put it simply, learning Grunt is learning how to write configuration files
III. package.json
General format is as follows:
{
"name": "project name",
"version": "project version number",
"description": "project description",
"author": "project creator",
"license": "project copyright",
"devDependencies": {
// project dependent plugins
}
}
For example, a small project's package.json:
{
"name": "world",
"version": "0.4.0",
"devDependencies": {
"grunt": "~0.4.2",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-jshint": "~0.6.3",
"grunt-contrib-uglify": "~0.2.2",
"grunt-contrib-watch": "^0.6.1"
}
}
After writing package.json, cd into the directory via command line, execute npm install, download the declared dependencies, they will be placed in the node_modules folder under current directory
When needing to add dependencies, just use npm install grunt-contrib-XXX --save-dev, it can automatically update package.json content
Note:
-
Cannot have comments, otherwise npm install parsing fails (no matter what form of comments, whether at file beginning, end or elsewhere... all won't work)
-
version must be in X.X.X format, X.X will error
Actually version format has complex standards, please see http://semver.org/
- Command like npm install grunt-contrib-XXX --save-dev can automatically update package.json
The last dependency module grunt-contrib-watch was added this way
- What do ~ and ^ before version numbers mean?
Didn't see any materials explaining this, but we can guess: ^ means it will look for latest version, while ~ means specified version (might be same as git's HEAD^ and HEAD~n... of course, just guessing)
Generally use ~ to specify concrete version, because there might be plugin compatibility and stability issues
P.S. If you know reliable explanation, please tell me, thank you
- Automatically generate package.json
Type npm init in command line and follow command line prompts step by step to complete, tested not very useful, recommend writing by hand, or write a commonly used template, force reuse
III. Gruntfile.js
General format is as follows:
module.exports = function(grunt){
// 1. Define tasks
grunt.initConfig({
// 1. Read package.json
pkg: grunt.file.readJSON('package.json'),
// 2. Initialize configuration objects for each task
task1: {
options: {
// Set configuration options
},
build: {
// Set input/output paths, etc.
}
},
task2: {
// ...
}
});
// 2. Load plugins
grunt.loadNpmTasks('Grunt plugin name');
// 3. Register tasks
grunt.registerTask('default',['Grunt task']);
grunt.registerTask('mytask',['task1', 'task3']);
};
For example, a small project's package.json:
module.exports = function(grunt) {
// 1. Define tasks
grunt.initConfig({
// 1. Read package.json
pkg: grunt.file.readJSON("package.json"),
// 2. Initialize configuration objects for each task
// Concatenate files
concat: {
options: {
// Prevent concatenation errors (missing semicolon at end of previous file)
separator: ";",
// Top information (need to bring your own comment format, doesn't auto-comment, doesn't auto-line-break)
banner: "/*<%= pkg.name %>_<%= pkg.version %> " +
// *Note*: yyyy-mm-dd needs quotes, indicating string parameter
"<%= grunt.template.today('yyyy-mm-dd') %>*/\r\n\r\n",
// Bottom information
footer: "\r\n\r\n/* author: http://ayqy.net/ */"
},
build: {
src: ["src/w.js", "src/Const.js", "src/Item.js", "src/Map.js", "src/Util.js", "src/Core.js"],
dest: "build/<%= pkg.name %>.js"
}
},
// Code checking
jshint: {
options: {
eqeqeq: true, // Require ===
trailing: true, // Require no trailing spaces
//unused: true, // Require warning for unused variables (modular code will error)
forin: true, // Require for-in must have hasOwnProp filter
curly: true // Require curly braces
},
files: ["Gruntfile.js", "src/*.js"]
},
// Code minification
uglify: {
options: {
// Don't mangle variable names
mangle: false,
// Output compression rate, optional values are false(don't output info), gzip
report: "min",
// Top information (need to bring your own comment format, doesn't auto-comment, doesn't auto-line-break)
banner: "/*<%= pkg.name %>_<%= pkg.version %> " +
"<%= grunt.template.today('yyyy-mm-dd') %>*/\r\n\r\n",
// Bottom information
footer: "\r\n\r\n/* author: http://ayqy.net/ */"
},
build: {
files: {
// <%= concat.dist.dest %> means uglify will automatically minify files generated in concat task
"build/<%= pkg.name %>.min.js": ["<%= concat.build.dest %>"]
}
}
},
// Listen for file changes, automatically execute tasks
watch: {
files: ["<%= jshint.files %>"],
tasks: ["default"]
}
});
// 2. Load plugins
grunt.loadNpmTasks("grunt-contrib-concat");
grunt.loadNpmTasks("grunt-contrib-jshint");
grunt.loadNpmTasks("grunt-contrib-uglify");
grunt.loadNpmTasks("grunt-contrib-watch");
// 3. Register tasks
grunt.registerTask("default", ["jshint", "concat", "uglify"]); // Default task
grunt.registerTask("check", ["jshint"]); // Custom task: code checking
};
After writing Gruntfile.js, no need to execute num install or similar commands, just use grunt TaskName to execute corresponding tasks directly. For example: grunt executes default task, grunt jshint executes code checking, grunt mytask executes a series of tasks in order, etc.
If there are multiple targets, can use grunt TaskName*: (English half-width colon)*TargetName to execute specified target. When registering tasks, can also use TaskName:TargetName to specify target
P.S. As for what target is, please continue reading below. Configuring Gruntfile.js might be a bit troublesome, but fortunately only need to configure once, can use directly afterwards. May not fully understand some details, please be sure to finish reading the Note section below
Note:
- Which to use between dist and build?
Common are options-dist and options-build, both can be used, because names don't matter
Only options is what matters, for example we can do this:
concat: {
options: {
separator: ";"
},
xx: {
src: "src/*.js",
dest: "<%= pkg.name %>.js"
}
}
Of course can also do this:
concat: {
options: {
separator: ";"
},
xx: {
src: "src/*.js",
dest: "<%= pkg.name %>.js"
},
xxx: {
src: "src/*.js",
dest: "<%= pkg.name %>.js"
}
}
Then execute grunt concat, will execute xx and xxx in sequence. So if there's only one target (both xx and xxx are called targets), using build and dist makes no difference, because no need for semantic distinction
If there are multiple targets, better to choose some semantically friendly names
P.S. Personally prefer build, of course, names don't matter, so some tutorials even have bar, foo, etc., which is confusing
- About options
Above examples show grunt only recognizes options (Note: missing 1 's' won't work~), names that aren't options are all treated as targets to execute
Above examples are all target-level options, actually can also have task-level options, can affect all targets under task. Of course, doesn't matter if you don't know this, just write more code
-
Registering same-name tasks will cause infinite recursion
grunt.registerTask("concat", ["concat"]); -
Can give tasks aliases
grunt.registerTask("check", ["jshint"]); // Custom task: code checking -
More examples
If need more examples to help understand, recommend writing a small project yourself, test slowly
If really don't have much time, please see CnBlogs: Grunt Usage Notes - uglify: Most Complete uglify Usage DEMO
IV. Online Resources
- Don't know which plugin can meet requirements, stable, easy to use
http://www.gruntjs.net/plugins
Link page gives top 100 plugins by downloads in last 30 days, with function introduction, last update time, etc. Click to jump to corresponding npm official website plugin homepage. Also supports search, very convenient
- Don't know what configuration options XX plugin has
Link page is npm official website, fill in plugin name in search box, for example grunt-contrib-watch
Plugin homepage provides detailed configuration instructions and examples, for example watch configuration options:
Simplest usage:
watch: {
files: ['**/*'],
tasks: ['jshint']
}
Or complex:
watch: {
sass: {
// We watch and compile sass files as normal but don't live reload here
files: ['src/sass/*.sass'],
tasks: ['sass']
},
livereload: {
// Here we watch the files the sass task will compile to
// These files are sent to the live reload server after sass compiles to them
options: { livereload: true },
files: ['dest/**/*']
}
}
3. Grunt API
Link page has all Grunt APIs, such as grunt.log, grunt.initConfig, etc., etc. Go check when seeing new things
References
-
W3CPlus: Grunt Tutorial -- First Contact with Grunt: Much better than most beginner tutorials
-
Grunt Chinese Official Website: Not recommended
-
Grunt English Official Website: Strongly recommended
-
CnBlogs: [Grunt Integrated Version] Learn to Use Grunt to Package Frontend Code in 30 Minutes: Can watch this if you can endure loneliness...
No comments yet. Be the first to share your thoughts.