大多數開發人員都一致認爲,JavaScript開發的速度和節奏在過去的幾年裏已經至關驚人。不論是Backbone.js和Ember.js的框架仍是JS Bin社區,這種語言的發展變化不只提升咱們網站的用戶體驗,並且咱們也在開始使用他們。javascript
當您在使用JavaScript,您可能須要按期執行多個任務。雖然這在大多項目中都存在,但切實是一個耗時的和重複的工做方式。在這樣一個活躍的社區,你會假設工具均可以自動化,加快這個過程。此時就出現了Grunt。php
創建在Node.js之上,Grunt是一個基於命令行的工具,用於加快工做流程,減小用於生前以前所作的準備。它能夠結速工做與自動編譯一同進行。基本上,你可使用Grunt的大部分任務來幫你處理你認爲乏味的,一般須要手工配置和運行的工做。css
雖然早期版本附帶了JSHint和Uglyify插件,但最近的版本(版本0.4)依賴於插件作一切事情。html
什麼樣的任務?這有一個詳細的列表。我只想說,Grunt能夠處理大部你想處理的事情,從壓縮到加載JavaScript。他也能夠用於與JavaScript無關的一系列任務,好比說將Sass和LESS編譯成CSS。咱們甚至使用blink當構建失敗時通知咱們。前端
最爽的事情之一就是Grunt讓團隊作到一致性。若是你的工做是協做型的,你將要知道在代碼中不一致性多麼使人煩惱的。Grunt工做使用團隊具備 統一的命令,從而確保團隊中的每一個人都使用相同的標準來編寫代碼。畢竟,由於在團隊中如何編寫代碼這樣的小問題引發項目失敗更讓人感到沮喪。java
Grunt也有一個使人難以置信的活躍社區,開發人員會在社區中按期發佈新插件。進入的門檻相對較低,由於一個普遍的工具和自動執行的任務就可使用。node
使用Grunt的首要事情就是設置Node.js。(若是你對Node.js一無所知,別擔憂,它只是安裝爲Grunt可以運行)。git
一量你安裝好了Node.js,你能夠終端命令中輸入:github
$ npm install -g grunt-cli
爲了確保Grunt已經正確安裝,你能夠運行下面的命令:web
$ grunt --version
接下來在你項目的根目中建立一個package.json
和一個Gruntfile.js
文件。
//測試項目(SampleGrunt)目錄結構
+SampleGrunt +----Gruntfile.js +----package.json
JSON文件使咱們能跟蹤和安裝咱們全部開發所依賴的信息。而後,對項目工做的人會擁有當前開發依賴性,最終有助於保持同步的開發環境。
在你項目根據下建立一個文件,而且包含下面的信息:
{
"name":"SampleGrunt", "version":"0.1.0", "author":"Brandon Random", "private":true, "devDependencies":{ "grunt":"~0.4.0" } }
一旦你這樣作了,運行下面的命令:
$ npm install
這告訴npm
所需的依賴關係,而後把它們安裝在node_modules
目錄中。
這個時候,你的項目的根目錄下會新增長一個node_modules
的目錄:
+SampleGrunt +----Gruntfile.js +----node_modules +----package.json
Gruntfile.js
本質上是一個函數,並且他的參數是grunt
。
module.exports = function(grunt){ grunt.initConfig({ pkg:grunt.file.readJSON('package.json') }); grunt.registerTask('default',[]); };
你如今能夠在你的項目根根目錄下運行Grunt命令。可是在這個階段你這樣作,你將會看到如下的警告信息:
$ grunt > Task "default" not found. Use --force to continue.
獲得這樣的信息是由於咱們除了Grunt以外沒有指定任何任務和依賴。因此,讓咱們這樣作。但首先,讓咱們看看如何擴展package.json
文件。
最好是經過Node.js來處理,它能夠找到安裝包並將他們安裝在一塊兒,並且只基於包文件的內容。安裝全部新的依賴關係,只須要在文件中添加下面的內容:
{
"name":"SampleGrunt", "version":"0.1.0", "author":"Brandon Random", "private":true, "devDependencies":{ "grunt":"~0.4.0", "grunt-contrib-cssmin":"*", "grunt-contrib-sass":"*", "grunt-contrib-uglify":"*", "grunt-contrib-watch":"*", "grunt-cssc":"*", "grunt-htmlhint":"*", "matchdep":"*" } }
在命令行中輸入下面命令能夠完成安裝流程:
$ npm install
執行完上面的命令後,全部的依賴關係都將安裝在node_modules
目錄中:
+SampleGrunt +----Gruntfile.js +----node_modules +++----css-condense +++----grunt +++----grunt-contrib-cssmin +++----grunt-contrib-sass +++----grunt-contrib-uglify +++----grunt-contrib-watch +++----grunt-cssc +++----grunt-htmlhint +++----matchdep +----package.json
如今任務包已安裝好了,他們已經加載到Grunt中,咱們如今能用他們作些什麼。使用matchdep
咱們可使用一行代碼加載全部的任務。這是很好的一點,由於如今依賴關係的列表都只包括了包文件。
在頂部的Gruntfile.js
的grunt.initConfig
上面粘貼下面的一段代碼:
require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);
沒有matchdep
,咱們須要爲每一個依賴關係寫grunt.loadNpmTasks('grunt-task-name')
,這將很快增長和安裝其餘插件。
由於插件加載到Grunt中,咱們有可能會指定開始選項。首先是HTML文件(index.html),包含下面的內容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"> <title>Enter your first name</title> <link rel="stylesheet" href="build/css/master.css"> </head> <body> <label for="firstname">Enter your first name</label> <input id="firstname" name="firstname" type="text"> <p id="namevalidation" class="validation"></p> <script type="text/javascript" src="build/js/base.min.js"></script> </body> </html>
在grunt.initConfig
中添加這樣的配置:
htmlhint: {
build: {
options: {
'tag-pair':true, 'tagname-lowercase':true, 'attr-lowercase':true, 'attr-value-double-quotes':true, 'doctype-first':true, 'spec-char-escape':true, 'id-unique':true, 'head-script-disabled':true, 'style-disabled':true }, src:['index.html'] } }
一個插件的配置一般是這樣的:插件的名稱(不帶grunt-contrib-/grunt-
前綴)而後是你選擇的一個或更多的目標(能夠用於建立自定義插件的文件),一個options
對象,和這個文件效果。如今你在終端運行grunt htmlhint
,它會查看源文件,並確保咱們的HTML沒有錯誤!然而,一小時手動輸入這個命令數次,將讓你的工做很快變得乏味。
在命令的終端執行grunt htmlhint
命令後,若是index.html
沒有出錯時,在終端會有信息提出:
Running "htmlhint:build" (htmlhint) task >> 0 files lint free. Running "htmlhint:src" (htmlhint) task >> 1 file lint free.
watch
任務能夠根據被保存的文件運行一個獨特的任務。在grunt.initConfig
加入下面的代碼:
watch: { html: { files:['index.html'], tasks:['htmlhint'] } }
而後在終端運行grunt watch
。你會在終端看到下面的提示信息:
Running "watch" task Waiting...
如今嘗試在index.html
中添加一個註釋。你會注意到,當文件被保存,驗證是自動執行的!你會在終端看到對應的信息:
Running "watch" task Waiting...OK >> File "index.html" changed. Running "htmlhint:build" (htmlhint) task >> 0 files lint free. Running "htmlhint:src" (htmlhint) task >> 1 file lint free. Done, without errors. Completed in 0.538s at Fri Nov 01 2013 22:54:03 GMT+0800 (CST) - Waiting...
這對於開發者來講是一個很好的東西,由於它意味着,你在編寫代碼的時候他會默默的進行驗證,若是代碼沒有經過驗證測試的時候他會失敗(和它會告訴你是什麼問題引發的錯誤)。
注意,grunt watch
將會一直運行,直到關閉終端或者直到它中止(在Mac上執行control + c
能夠直接中止grunt watch
命令)。
讓咱們建立一個JavaScript文件來驗證一個用戶名。儘量我能夠分簡單,咱們將檢查的只是非字母字符。咱們也會利用JavaScript的strict
模式,它阻止咱們品尼高有效但質量差勁的JavaScript。把下面的代碼粘貼到assets/js/base.js
:
function Validator(){ "use strict"; } Validator.prototype.checkName = function(name) { "use strict"; return(/[^a-z]/i.test(name) === false); }; window.addEventListener('load',function(){ "use strict"; document.getElementById('firstname').addEventListener('blur',function(){ var _this = this; var validator = new Validator(); var validation = document.getElementById('namevalidation'); if (validator.checkName(_this.value) === true){ validation.innerHTML = 'Looks good! :)'; validation.className = 'validation yep'; _this.className = "yep"; } else { validation.innerHTML = 'Looks bad! :('; validation.className = "validation nope"; _this.className = "nope"; } }); });
咱們使用UglifyJS來壓縮這個文件,在grunt.initConfig
中加入下面代碼:
uglify: { build: { files: { 'build/js/base.min.js' : ['assets/js/base.js'] } } }
UglifyJS壓縮咱們源文件中全部的變量和函數名,讓咱們文件儘量少的佔用空間,而後剪去空白和註釋——很是適合用於生產的JavaScript。接着,咱們須要爲咱們的Uglify的JavaScript建立一個watch
任務。將下面的代碼添加到watch
配置中:
watch: { js: { files: ['assets/js/base.js'], tasks: ['uglify'] } }
Sass用來處理CSS是使人難以置信的有用,特別是在一個團隊。一般在源文件中寫更少的代碼,由於Sass可使用函數和變量產生大的CSS代碼 塊。如何使用Sass自己有點超出了本文的範圍,因此,在這個階段你還不習慣和學習一個預處理器,你能夠跳過這一節。咱們將介紹一個很是簡單的用例,使用 具備變量和混合的SCSS,這很是相似於CSS!
Grunt的Sass插件須要sass gem
。你將須要在你的系統上安裝Ruby。你能夠在你的終端使用下面的命令檢查你的系統是否安裝了Ruby:
ruby -v
若是你的系統已經安裝了Ruby,在終端執行上面的命令會獲得以下所示的提示信息:
ruby 1.9.3p392 (2013-02-22 revision 39386) [x86_64-darwin12.4.0]
接下來運行下面的命令安裝Sass:
gem install sass
有關於Sass的更多教程,你能夠點擊這裏查閱。——大漠
根據您的配置,你能夠須要經過sudo
命令來運行這個命令——例如sudo gem install sass
——這個時候終端會要求你輸入你的電腦登陸密碼。當Sass安裝好後,建立一個新的目錄叫做assets
,並在裏面建立另外一個叫sass
目錄。在這個目錄中建立一個新的文件名master.scss
,並將下面的代碼粘貼進行:
@mixin prefix($property, $value, $prefixes: webkit moz ms o spec) { @each $p in $prefixes { @if $p == spec { #{$property}: $value; } @else { -#{$p}-#{$property}: $value; } } } $input_field: #999; $input_focus: #559ab9; $validation_passed: #8aba56; $validation_failed: #ba5656; $bg_colour: #f4f4f4; $box_colour: #fff; $border_style: 1px solid; $border_radius: 4px; html { background: $bg_colour; } body { width: 720px; padding: 40px; margin: 80px auto; background: $box_colour; box-shadow: 0 1px 3px rgba(0, 0, 0, .1); border-radius: $border_radius; font-family: sans-serif; } input[type="text"] { @include prefix(appearance, none, webkit moz); @include prefix(transition, border .3s ease); border-radius: $border_radius; border: $border_style $input_field; width: 220px; } input[type="text"]:focus { border-color: $input_focus; outline: 0; } label, input[type="text"], .validation { line-height: 1; font-size: 1em; padding: 10px; display: inline; margin-right: 20px; } input.yep { border-color: $validation_passed; } input.nope { border-color: $validation_failed; } p.yep { color: $validation_passed; } p.nope { color: $validation_failed; }
你將發現SCSS擴展起來比傳統的Sass更像CSS。這個樣式表中使用了Sass的兩個特性:混合(mixins)和變量(variables)。Mixins
就像一個函數,能夠將一些參數傳遞給它,用來構造CSS塊,而後重用。
變量是特別有用的十六進制顏色,咱們能夠是構建一個調色板,能夠在一個地方改變,很是快的調整整個方面設計。Mixin能夠用於前綴等規則上,例如appearance
和transition
等屬性,它能夠減小寫不少重複性代碼。
在處理大型樣式表時,當一個團隊的其餘成員想要更新一個樣式,什麼方法能夠減小行數使用文件易於閱讀。
除了Sass,Grunt-cssc和CSS規則結合在一塊兒,確保生成的CSS有最和的重複代碼。在中大型項目是有不少風格是重複的,這顯得很是的有用。然而,輸出的文件並不老是總小的。這樣就出現了cssmin
任務。它不只能夠去掉代碼中的空格,並且琮能夠將顏色轉換成最短值(所以,white
將轉換成#fff
)。在Gruntfile.js
中加入下面的任務:
cssc: {
build: {
options: {
consolidateViaDeclarations: true, consolidateViaSelectors: true, consolidateMediaQueries: true }, files: { 'build/css/master.css':'build/css/master.css' } } }, cssmin: { build: { src: 'build/css/master.css', dest: 'build/css/master.css' } }, sass: { build: { files: { 'build/css/master.css':'assets/sass/master.scss' } } }
如今,咱們有一些在適當的地方處理樣式表,這些任務也應該自動運行。build
目錄是Grunt自動建立的,用來放置腳本,CSS和(若是這是一個完整的網站)壓縮圖像。這意味着assets
目錄是用於放置開發的文件,裏面文件內容有可能有大量的註釋或不少文件,然而build
目錄,是用來放置用於生產環境所需的文件,裏面只留下了心樣能優化後的文件。
咱們將定義一組新的任務來處理CSS。在gruntfile.js
中添加下面的代碼,下面是默認的task
:
grunt.registerTask('buildcss', ['sass', 'cssc', 'cssmin']);
如今,當運行grunt buildcss
,全部CSS任務將一個接一個執行。這遠比運行grunt sass
,接着grunt cssc
,接着grunt cssmin
更快。咱們能夠經過配置watch
作全部更新,自動運行。
watch: { css: { files: ['assets/sass/**/*.scss'], task: ['buildcss'] } }
在運行grunt buildcss
命令後,命令終端運行有關於CSS方面的任務,命令端將顯示:
Running "sass:build" (sass) task Running "cssc:build" (cssc) task File "build/css/master.css" created. Running "cssmin:build" (cssmin) task File build/css/master.css created. Done, without errors.
同時,項目根目錄下將自動建立一個build
目錄,此時整個項目目錄結構以下:
+SampleGrunt +----assets +++----js +++----sass +----build +++----css +----Gruntfile.js +----node_modules +++----css-condense +++----grunt +++----grunt-contrib-cssmin +++----grunt-contrib-sass +++----grunt-contrib-uglify +++----grunt-contrib-watch +++----grunt-cssc +++----grunt-htmlhint +++----matchdep +----package.json
這路徑你看起來有點奇怪。基本上,它會依次檢查assets/sass
目錄下全部目錄中的.scss
文件,它充行咱們建立儘量多的Sass文件,而無需在gruntfile.js
中添加路徑。添加這個以後,gruntfile.js
將會像下面這樣:
module.exports = function(grunt){
"use strict"; require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks); grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), cssc: { build: { options: { consolidateViaDeclarations: true, consolidateViaSelectors: true, consolidateMediaQueries: true }, files: { 'build/css/master.css': 'build/css/master.css' } } }, cssmin: { build: { src: 'build/css/master.css', dest: 'build/css/master.css' } }, sass: { build: { files: { 'build/css/master.css': 'assets/sass/master.scss' } } }, watch: { html: { files: ['index.html'], tasks: ['htmlhint'] }, js: { files: ['assets/js/base.js'], tasks: ['uglify'] }, css: { files: ['assets/sass/**/*.scss'], tasks: ['buildcss'] } }, htmlhint: { build: { options: { 'tag-pair': true, // Force tags to have a closing pair 'tagname-lowercase': true, // Force tags to be lowercase 'attr-lowercase': true, // Force attribute names to be lowercase e.g. <div id="header"> is invalid 'attr-value-double-quotes': true, // Force attributes to have double quotes rather than single 'doctype-first': true, // Force the DOCTYPE declaration to come first in the document 'spec-char-escape': true, // Force special characters to be escaped 'id-unique': true, // Prevent using the same ID multiple times in a document 'head-script-disabled': true, // Prevent script tags being loaded in the for performance reasons 'style-disabled': true // Prevent style tags. CSS should be loaded through }, src: ['index.html'] } }, uglify: { build: { files: { 'build/js/base.min.js': ['assets/js/base.js'] } } } }); grunt.registerTask('default', []); grunt.registerTask('buildcss', ['sass', 'cssc', 'cssmin']); };
咱們如今有一個靜態的HTML頁面,一個放了Sass和JavaScript資源的assets
目錄,以及一個放了整理的CSS和JavaScript文件在build
目錄中,以及一個package.json
和gruntfile.js
文件。
如今,你應該有一個很堅實的基礎,能夠進一步探討Grunt。正如前面所提到的,一個使人難以置信的活躍的開發者社區在不斷的提供前端插件。個人建議是,請到插件庫查閱這300多個插件。
譯者手語:整個翻譯依照原文線路進行,並在翻譯過程略加了我的對技術的理解。若是翻譯有不對之處,還煩請同行朋友指點。謝謝!
如需轉載,煩請註明出處:
英文原文:http://coding.smashingmagazine.com/2013/10/29/get-up-running-grunt/