# 快速入門
Grunt和 Grunt 插件是通過?[npm](https://npmjs.org/)?安裝并管理的,npm是?[Node.js](http://nodejs.org/)?的包管理器。
*Grunt 0.4.x 必須配合Node.js?`>= 0.8.0`版本使用。;奇數版本號的 Node.js 被認為是不穩定的開發版。*
在安裝 Grunt 前,請確保當前環境中所安裝的?[npm](https://npmjs.org/)?已經是最新版本,執行?`npm update -g npm`?指令進行升級(在某些系統中可能需要?`sudo`?指令)。
如果你已經安裝了 Grunt,現在需要參考一些文檔手冊,那就請看一看?[`Gruntfile`?實例](http://www.gruntjs.net/sample-gruntfile)?和如何?[配置任務](http://www.gruntjs.net/configuring-tasks)吧。
## 安裝 CLI
**還在使用 Grunt 0.3 版本嗎?請查看?[Grunt 0.3 注意事項](http://www.gruntjs.net/upgrading-from-0.3-to-0.4#grunt-0.3-notes)**
在繼續學習前,你需要先將Grunt命令行(CLI)安裝到全局環境中。安裝時可能需要使用sudo(針對OSX、*nix、BSD等系統中)權限或者作為管理員(對于Windows環境)來執行以下命令。
~~~
npm install -g grunt-cli
~~~
上述命令執行完后,`grunt`?命令就被加入到你的系統路徑中了,以后就可以在任何目錄下執行此命令了。
注意,安裝`grunt-cli`并不等于安裝了 Grunt!Grunt CLI的任務很簡單:調用與`Gruntfile`在同一目錄中 Grunt。這樣帶來的好處是,允許你在同一個系統上同時安裝多個版本的 Grunt。
這樣就能讓多個版本的 Grunt 同時安裝在同一臺機器上。
## CLI 是如何工作的
每次運行`grunt`?時,他就利用node提供的`require()`系統查找本地安裝的 Grunt。正是由于這一機制,你可以在項目的任意子目錄中運行`grunt`?。
如果找到一份本地安裝的 Grunt,CLI就將其加載,并傳遞`Gruntfile`中的配置信息,然后執行你所指定的任務。為了更好的理解 Grunt CLI的執行原理,請[閱讀源碼](https://github.com/gruntjs/grunt-cli/blob/master/bin/grunt)。
## 拿一份現有的 Grunt 項目練手
假定Grunt CLI已經正確安裝,并且已經有一份配置好`package.json`?和?`Gruntfile`?文件的項目了,接下來就很容易拿Grunt練手了:
1. 將命令行的當前目錄轉到項目的根目錄下。
2. 執行`npm install`命令安裝項目依賴的庫。
3. 執行?`grunt`?命令。
OK,就是這么簡單。還可以通過`grunt --help`?命令列出所有已安裝的Grunt任務(task),但是一般更建議去查看項目的文檔以獲取幫助信息。
## 準備一份新的 Grunt 項目
一般需要在你的項目中添加兩份文件:`package.json`?和?`Gruntfile`。
**package.json**: 此文件被[npm](https://npmjs.org/)用于存儲項目的元數據,以便將此項目發布為npm模塊。你可以在此文件中列出項目依賴的grunt和Grunt插件,放置于[devDependencies](https://docs.npmjs.com/files/package.json#devdependencies)配置段內。
**Gruntfile**: 此文件被命名為?`Gruntfile.js`?或?`Gruntfile.coffee`,用來配置或定義任務(task)并加載Grunt插件的。?**此文檔中提到的?`Gruntfile`?其實說的是一個文件,文件名是?`Gruntfile.js`?或`Gruntfile.coffee`**。
## package.json
`package.json`應當放置于項目的根目錄中,與`Gruntfile`在同一目錄中,并且應該與項目的源代碼一起被提交。在上述目錄(`package.json`所在目錄)中運行`npm install`將依據`package.json`文件中所列出的每個依賴來自動安裝適當版本的依賴。
下面列出了幾種為你的項目創建`package.json`文件的方式:
* 大部分?[grunt-init](http://www.gruntjs.net/project-scaffolding)?模版都會自動創建特定于項目的`package.json`文件。
* [npm init](https://docs.npmjs.com/cli/init)命令會創建一個基本的`package.json`文件。
* 復制下面的案例,并根據需要做擴充,參考此[說明](https://docs.npmjs.com/files/package.json).
~~~
{
"name": "my-project-name",
"version": "0.1.0",
"devDependencies": {
"grunt": "~0.4.5",
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-nodeunit": "~0.4.1",
"grunt-contrib-uglify": "~0.5.0"
}
}
~~~
### 安裝Grunt 和 grunt插件
向已經存在的`package.json`?文件中添加Grunt和grunt插件的最簡單方式是通過`npm install <module> --save-dev`命令。此命令不光安裝了`<module>`,還會自動將其添加到[devDependencies](https://docs.npmjs.com/files/package.json#devdependencies)?配置段中,遵循[tilde version range](https://npmjs.org/doc/misc/semver.html#Ranges)格式。
例如,下面這條命令將安裝Grunt最新版本到項目目錄中,并將其添加到devDependencies內:
~~~
npm install grunt --save-dev
~~~
同樣,grunt插件和其它node模塊都可以按相同的方式安裝。下面展示的實例就是安裝 JSHint 任務模塊:
~~~
npm install grunt-contrib-jshint --save-dev
~~~
在?[Grunt 插件](http://www.gruntjs.net/plugins)?頁面可以看到當前可用的 Grunt 插件,他們可以直接在項目中安裝并使用。
安裝插件之后,請務必確保將更新之后的?`package.json`?文件提交到項目倉庫中。
## Gruntfile
`Gruntfile.js`?或?`Gruntfile.coffee`?文件是有效的 JavaScript 或 CoffeeScript 文件,應當放在你的項目根目錄中,和`package.json`文件在同一目錄層級,并和項目源碼一起加入源碼管理器。
Gruntfile由以下幾部分構成:
* "wrapper" 函數
* 項目與任務配置
* 加載grunt插件和任務
* 自定義任務
### Gruntfile文件案例
在下面列出的這個?`Gruntfile`?中,`package.json`文件中的項目元數據(metadata)被導入到 Grunt 配置中,?[grunt-contrib-uglify](http://github.com/gruntjs/grunt-contrib-uglify)?插件中的`uglify`?任務(task)被配置為壓縮(minify)源碼文件并依據上述元數據動態生成一個文件頭注釋。當在命令行中執行?`grunt`?命令時,`uglify`?任務將被默認執行。
~~~
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
src: 'src/<%= pkg.name %>.js',
dest: 'build/<%= pkg.name %>.min.js'
}
}
});
// 加載包含 "uglify" 任務的插件。
grunt.loadNpmTasks('grunt-contrib-uglify');
// 默認被執行的任務列表。
grunt.registerTask('default', ['uglify']);
};
~~~
前面已經向你展示了整個?`Gruntfile`,接下來將詳細解釋其中的每一部分。
### "wrapper" 函數
每一份?`Gruntfile`?(和grunt插件)都遵循同樣的格式,你所書寫的Grunt代碼必須放在此函數內:
~~~
module.exports = function(grunt) {
// Do grunt-related things in here
};
~~~
### 項目和任務配置
大部分的Grunt任務都依賴某些配置數據,這些數據被定義在一個object內,并傳遞給[grunt.initConfig](http://www.gruntjs.net/grunt#grunt.initconfig)?方法。
在下面的案例中,`grunt.file.readJSON('package.json')`?將存儲在`package.json`文件中的JSON元數據引入到grunt config中。 由于`<% %>`模板字符串可以引用任意的配置屬性,因此可以通過這種方式來指定諸如文件路徑和文件列表類型的配置數據,從而減少一些重復的工作。
你可以在這個配置對象中(傳遞給initConfig()方法的對象)存儲任意的數據,只要它不與你任務配置所需的屬性沖突,否則會被忽略。此外,由于這本身就是JavaScript,你不僅限于使用JSON;你可以在這里使用任意的有效的JS代碼。如果有必要,你甚至可以以編程的方式生成配置。
與大多數task一樣,[grunt-contrib-uglify](http://github.com/gruntjs/grunt-contrib-uglify)?插件中的`uglify`?任務要求它的配置被指定在一個同名屬性中。在這里有一個例子, 我們指定了一個`banner`選項(用于在文件頂部生成一個注釋),緊接著是一個單一的名為`build`的uglify目標,用于將一個js文件壓縮為一個目標文件。
~~~
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
src: 'src/<%= pkg.name %>.js',
dest: 'build/<%= pkg.name %>.min.js'
}
}
});
~~~
### 加載 Grunt 插件和任務
像?[concatenation](https://github.com/gruntjs/grunt-contrib-concat)、[minification]、[grunt-contrib-uglify](http://github.com/gruntjs/grunt-contrib-uglify)?和?[linting](https://github.com/gruntjs/grunt-contrib-jshint)這些常用的任務(task)都已經以[grunt插件](https://github.com/gruntjs)的形式被開發出來了。只要在?`package.json`?文件中被列為dependency(依賴)的包,并通過`npm install`安裝之后,都可以在`Gruntfile`中以簡單命令的形式使用:
~~~
// 加載能夠提供"uglify"任務的插件。
grunt.loadNpmTasks('grunt-contrib-uglify');
~~~
**注意:**?`grunt --help`?命令將列出所有可用的任務。
### 自定義任務
通過定義?`default`?任務,可以讓Grunt默認執行一個或多個任務。在下面的這個案例中,執行?`grunt`?命令時如果不指定一個任務的話,將會執行`uglify`任務。這和執行`grunt uglify`?或者?`grunt default`的效果一樣。`default`任務列表數組中可以指定任意數目的任務(可以帶參數)。
~~~
// Default task(s).
grunt.registerTask('default', ['uglify']);
~~~
如果Grunt插件中的任務(task)不能滿足你的項目需求,你還可以在`Gruntfile`中自定義任務(task)。例如,在下面的?`Gruntfile`?中自定義了一個`default`?任務,并且他甚至不依賴任務配置:
~~~
module.exports = function(grunt) {
// A very basic default task.
grunt.registerTask('default', 'Log some stuff.', function() {
grunt.log.write('Logging some stuff...').ok();
});
};
~~~
特定于項目的任務不必在?`Gruntfile`?中定義。他們可以定義在外部`.js`?文件中,并通過[grunt.loadTasks](http://www.gruntjs.net/grunt/#grunt.loadtasks)方法加載。
## 擴展閱讀
* The?[Installing grunt](http://www.gruntjs.net/installing-grunt/)?guide has detailed information about installing specific, production or in-development, versions of Grunt and grunt-cli.
* The?[Configuring Tasks](http://www.gruntjs.net/configuring-tasks/)?guide has an in-depth explanation on how to configure tasks, targets, options and files inside the?`Gruntfile`, along with an explanation of templates, globbing patterns and importing external data.
* The?[Creating Tasks](http://www.gruntjs.net/creating-tasks/)?guide lists the differences between the types of Grunt tasks and shows a number of sample tasks and configurations.
* For more information about writing custom tasks or Grunt plugins, check out the?[developer documentation](http://www.gruntjs.net/grunt).