什麼是Grunt

當時學習 Grunt 的時候,真是很頭疼。分了兩個時間段,學習了兩次才硬啃下來,之後才能用在項目中。主要原因我認爲是學習資料和文檔上面寫的太高端了。這類的文檔或者資料有個顯著特點,上來先簡單介紹一下這個玩意(Grunt 是一個 JavaScript 任務運行器),然後就是如何安裝,直接給你配置文件的語法,如何使用插件,新手往往看完還不知所以然。

就像我第一次學習的時候,只是大體知道 Grunt 很火,大家都在用,但耐着心看文檔和一些別人的學習總結,還是困惑,這到底是個什麼東西?究竟幹什麼用?爲什麼要這麼麻煩配置這些東西?

到現在應用在項目中也有一小段時間了,稍微有一點點經驗,好吧,我決定寫一篇即便是新手也能馬上看懂的文章。

用途和使用場景

先不要管 Grunt,我們先來看下微硬公司小明和小紅的日常前端開發工作:

小明在開發一個 JS 插件,寫了好多代碼,終於寫完了,放在 HTML 文件裏調用一看,console 裏面好多 error,於是就挨個調整修改。爲了排除深層潛在問題,他還打開了 http://www.jshint.com/ 這個網站,把自己的代碼複製進去用 jshint 檢測了,結果發現了好多細節問題和不規範的地方,依次修改。最後要發佈了,他又打開了 http://tool.css-js.com/ 網站,把自己的代碼複製進去,使用 Uglify 來壓縮了一下,提供一個壓縮版本。然後上傳到了 Github 上託管。

這時候,Github 突然有一個 Issue,他看了一下,原來有個疏忽的地方,又進行了修改,然後打開 jsHint 和 Uglify 在線壓縮網站進行檢查和壓縮,再次發佈上去。

於此同時,小紅在做一個活動頁面的前端重構工作。她打開了正在做的 HTML 頁面,由於使用了 Sass,所以她打開了 Koala 在後臺幫她自動編譯成 CSS,但是每次保存一下,想要看到效果,還是需要切換到瀏覽器,刷新一下。做交互處理的時候,她寫了一些 JS,爲了規範,也使用 jshint 檢查了一下。終於做完了,這時候做了一下最後的優化處理準備上線,她把 icons 在 Photoshop 中合併成了一張圖片,並在 CSS 的對應位置修改了一下,然後用在線壓縮工具把 CSS 和 JS 都壓縮了一遍,提交測試去了。

這就是他倆的工作,日復一日年復一年,有一天,小明終於受夠了,朝小紅發牢騷:哥要是再來回複製粘貼到網站上排錯壓縮,哥就是逗逼!小紅滿眼淚花的說,你想好辦法了,幫我解決一下自動刷新問題,我也受夠了。

於是小明工作都不做了,開始苦思冥想怎麼開發一個可以自動把寫的代碼發送到遠程網站,讓他們檢查一下錯誤並且壓縮好,再反回來生成一個文件。

開發一個任務自動處理器

當然,小明很快就不那麼想了,因爲依賴外部網站有很多意外因素,而且受限於網絡和網速,其次他們也沒提供有關接口來調用。但是他們都提供了一些算法之類的工具等。這樣可以在本地調用這些工具,來完成這些操作,甚至連網絡也不需要。

小明愉快的開始在筆記本上構思這個工具的開發方法和需要的功能:

首先我需要先開發一個工具,可以調用這個工具對我的某個項目目錄裏面的項目文件做一些操作,比如壓縮、查錯、合併等。

如果要做成一個工具,可能不太好,或許別人還需要更多功能,但是我沒法開發這麼多功能啊。要不我就做個框架把,然後每個功能做成一個插件,比如壓縮插件、合併插件。如果有人需要在他的項目裏壓縮某個文件,他安裝一下我這個工具然後再安裝壓縮插件就好了。這樣有更多需求的人,可以自己編寫功能插件,然後配合我的工具使用。

慢着,他安裝完了工具和插件之後,要怎麼來調用這個插件來處理項目文件?在程序界面上選擇文件,然後勾選選項?我的天,我就會寫點 JS,哪裏可能開發帶有界面的程序?慢着,用 JS ?他可以在項目文件夾中編寫一個 JS 來設置任務啊!然後我的工具會讀取這個 JS,解析之後獲得他要執行的任務(比如壓縮某某文件並改名成某某),然後調用插件完成任務。

太棒了。但是插件這麼多,放在項目裏肯定很大,而且又是不相關代碼,要不等他發佈的時候自動刪除這些插件文件把?不行,如果他要發給別人,別人要繼續開發,還得重新安裝依次安裝這些插件,然後執行任務。那怎麼辦?要不我再用個文件記錄一下當前項目中安裝或者需要的插件把!這樣只需要把這個文件和 JS 任務文件放在項目目錄裏面,有需要的人,直接輸入一條命令安裝一下,然後立刻就可以執行了。

我太聰明瞭!

於是小明興奮的跑過去給小紅講了一下他的工具的開發思路,然後告訴她,他可以幫忙寫一個自動刷新的插件。小紅反而淡定的說:等等,我好像見過這種東西,這不是 Grunt 嘛?

小明抓緊搜了一下 Grunt,看了一下文檔之後,對着小紅:尼瑪,你爲什麼不早說!

開始學習 Grunt

Grunt 就是小明想的這樣一種自動化任務處理工具,它就是一個工具框架,有很多插件擴展它的功能。

Grunt 基於 Node.js ,用 JS 開發,這樣就可以藉助 Node.js 實現跨系統跨平臺的桌面端的操作,例如文件操作等等。此外,Grunt 以及它的插件們,都作爲一個 包 ,可以用 NPM 安裝進行管理。

所以 NPM 生成的 package.json 項目文件,裏面可以記錄當前項目中用到的 Grunt 插件,而 Grunt 會調用 Gruntfile.js 這個文件,解析裏面的任務(task)並執行相應操作。

如果你對 Node.js、NPM 這些名詞不太熟悉,建議先去搜索瞭解一下,因爲下面的命令會涉及到它們,但是本文不會過多介紹。

安裝 Grunt

Grunt 依賴 Node.js 所以在安裝之前確保你安裝了 Node.js。然後開始安裝 Grunt。

實際上,安裝的並不是 Grunt,而是 Grunt-cli,也就是命令行的 Grunt,這樣你就可以使用 grunt 命令來執行某個項目中的 Gruntfile.js 中定義的 task 。但是要注意,Grunt-cli 只是一個命令行工具,用來執行,而不是 Grunt 這個工具本身。

安裝 Grunt-cli 需要使用 NPM,使用下面一行即可在全局範圍安裝 Grunt-cli ,換句話說,就是你可以在任何地方執行 grunt 命令:

npm install -g grunt-cli
需要注意,因爲使用 -g 命令會安裝到全局,可能會涉及到系統敏感目錄,如果用 Windows 的話,可能需要你用管理員權限,如果用 OS X / Linux 的話,你可能需要加上 sudo 命令。

下面我們新建一個項目目錄,並新建一些文件,這裏我準備了一份很簡單的項目,放在了 Github 上,下面操作將以此來操作,你可以下載或者 clone 下來: https://github.com/yujiangshui/gruntxx

生成 package.json 文件

這個 package.json 文件其實是 Node.js 來描述一個項目的文件,JSON 格式。生成這個文件超級簡單,推薦用命令行交互式的生成一下:

打開命令行,cd gruntxx 文件夾下面,輸入指令 npm init 之後,就出來很多信息,然後開始填寫項目名稱,填寫好了之後回車即可。其實這裏你一路回車下去也無妨,但是建議你細細的填一下,不明白的跳過好了。

這裏寫圖片描述

填寫好了之後,查看目錄就會發現生成 package.json 文件了,這樣就算生成好了。

其實就是一個文件而已,你覺得這種方式麻煩,完全可以新建一個文件,然後將類似下面的代碼複製進去,改一下對應選項,保存成 package.json 文件就可以:

{
“name”: “my-project-name”,
“version”: “0.1.0”,
“devDependencies”: {
}
}
最後我生成的代碼如下:

{
“name”: “gruntxx”,
“version”: “0.0.1”,
“description”: “學習 grunt”,
“repository”: {
“type”: “git”,
“url”: “https://github.com/yujiangshui/gruntxx.git
},
“author”: “Jiangshui”,
“license”: “MIT”,
“bugs”: {
“url”: “https://github.com/yujiangshui/gruntxx/issues
},
“homepage”: “https://github.com/yujiangshui/gruntxx
}
但這時我們還沒有在項目文件中安裝 Grunt 以及相關任務插件。

安裝 Grunt 和所需要的插件

就現在的這個示例項目而言,我打算讓 Grunt 幫忙實現下面幾個功能:檢查每個 JS 文件語法、合併兩個 JS 文件、將合併後的 JS 文件壓縮、將 SCSS 文件編譯、新建一個本地服務器監聽文件變動自動刷新 HTML 文件。

差不多就是這些,根據這些任務需求,需要用到:

合併文件:grunt-contrib-concat
語法檢查:grunt-contrib-jshint
Scss 編譯:grunt-contrib-sass
壓縮文件:grunt-contrib-uglify
監聽文件變動:grunt-contrib-watch
建立本地服務器:grunt-contrib-connect
它們的命名和文檔都很規範,因爲這些是官方提供的比較常用的插件。這些插件同時都是 NPM 管理的包,比如 grunt-contrib-concat - npm 你也可以在這上面看到用法等。

下面我們就要在這個項目中安裝這些插件,執行命令:

npm install grunt –save-dev
表示通過 npm 安裝了 grunt 到當前項目,同時加上了 –save-dev 參數,表示會把剛安裝的東西添加到 package.json 文件中。不信你打開 package.json 文件看下,是不是多了

“devDependencies”: {
“grunt”: “^0.4.5”
}
沒錯,這個的意思就是當前項目依賴 grunt,後面是它的版本,咱們不用管。如果安裝的時候沒有添加 –save-dev 參數,這裏就不會出現了,你需要自行添加上去。

下面我們來安裝 Grunt 的插件,當然,不需要一個個的安裝,太麻煩了,我們可以:

npm install –save-dev grunt-contrib-concat grunt-contrib-jshint grunt-contrib-sass grunt-contrib-uglify grunt-contrib-watch grunt-contrib-connect
等待一大串亂七八糟的下載狀態,我們把 grunt 和相關插件都安裝好了,不信看下是不是多了一個 node_modules 文件夾?打開看下,裏面就是咱們剛安裝的插件。

配置 Gruntfile.js 的語法

插件也裝好了,開始寫任務吧!既然是要程序來讀取執行,必要要有一定的語法規範,下面來簡單的說一下:

首先要明白,這是一個 JS 文件,你可以寫任意的 JS 代碼,比如聲明一個 對象 來存儲一會要寫任務的參數,或者是一個變量當作開關等等。

然後,所有的代碼要包裹在

module.exports = function(grunt) {

};
裏面。沒有爲什麼。

在這裏面的代碼,除去你自己寫的亂七八糟的 JS,與 Grunt 有關的主要有三塊代碼:任務配置代碼、插件加載代碼、任務註冊代碼。

顧名思義,這三塊代碼,任務配置代碼就是調用插件配置一下要執行的任務和實現的功能,插件加載代碼就是把需要用到的插件加載進來,任務註冊代碼就是註冊一個 task,裏面包含剛在前面編寫的任務配置代碼。

這樣,就可以用 grunt 來執行註冊的一個 task 從而根據任務配置代碼調用需要的插件來執行相應的操作。

下面來分別看一下這三塊代碼的寫法。

任務配置代碼

例如下面代碼:

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.initConfig 函數裏面,其中先寫了一句 pkg: grunt.file.readJSON(‘package.json’) 功能是讀取 package.json 文件,並把裏面的信息獲取出來,方便在後面任務中應用(例如下面就用了 <%= pkg.name %> 來輸出項目名稱),這樣可以提高靈活性。之後就是 uglify 對象,這個名字是固定的,表示下面任務是調用 uglify 插件的,首先先配置了一些全局的 options 然後新建了一個 build 任務。

也就是說,在 Uglify 插件下面,有一個 build 任務,內容是把 XX.js 壓縮輸出到 xx.min.js 裏面。如果你需要更多壓縮任務,也可以參照 build 多寫幾個任務。

至於怎麼寫出來 options 裏面的參數和 build 裏面的參數內容,這纔是 grunt 學習的難點,你需要查看每個插件的用法,根據用法來編寫任務,可以看下 grunt-contrib-uglify 的官方文檔,往下面拉你就可以看到參數和使用方法了。

這樣,我們就新建了一個基於 uglify 的任務 build,功能是把 src/<%= pkg.name %>.js 壓縮輸出 build/<%= pkg.name %>.min.js。

插件加載代碼

這個就超級簡單了,由於上面任務需要用到 grunt-contrib-uglify,當 grunt-contrib-uglify 安裝到我們的項目之後,寫下下面代碼即可加載:

grunt.loadNpmTasks(‘grunt-contrib-uglify’);
任務註冊代碼

插件也加載了,任務也佈置了,下面我們得註冊一下任務,使用

grunt.registerTask(‘default’, [‘uglify’]);
來註冊一個任務。上面代碼意思是,你在 default 上面註冊了一個 Uglify 任務,default 就是別名,它是默認的 task,當你在項目目錄執行 grunt 的時候,它會執行註冊到 default 上面的任務。

也就是說,當我們執行 grunt 命令的時候,uglify 的所有代碼將會執行。我們也可以註冊別的 task,例如:

grunt.registerTask(‘compress’, [‘uglify:build’]);
如果想要執行這個 task,我們就不能只輸入 grunt 命令了,我們需要輸入 grunt compress 命令來執行這條 task,而這條 task 的任務是 uglify 下面的 build 任務,也就是說,我們只會執行 uglify 裏面 build 定義的任務,而不會執行 uglify 裏面定義的其他任務。

這裏需要注意的是,task 的命名不能與後面的任務配置同名,也就是說這裏的 compress 不能命名成 uglify,這樣會報錯或者產生意外情況

OK,加上這三塊代碼,我們的示例 Gruntfile.js 就是這樣子的:

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’
}
}
});

// Load the plugin that provides the “uglify” task.
grunt.loadNpmTasks(‘grunt-contrib-uglify’);

// Default task(s).
grunt.registerTask(‘default’, [‘uglify’]);

};
這就是官方那個坑爹示例,貌似 uglify 的參數好像不對,反正我之前學習的時候,沒法運行這個配置,下面我們來根據示例項目和我們的需求配置一下。

配置 Gruntfile.js

先從簡單的入手,我們先來配置一下編譯 Scss 文件的 task。先新建一個 Gruntfile.js 文件,把大體的配置結構複製進去:

module.exports = function(grunt) {

var sassStyle = ‘expanded’;

grunt.initConfig({
pkg: grunt.file.readJSON(‘package.json’),
sass: {

}

});

grunt.loadNpmTasks(‘grunt-contrib-sass’);

grunt.registerTask(‘outputcss’,[‘sass’]);
grunt.registerTask(‘default’);

};
應該可以看懂把?這裏不再贅述了,我們來根據 Sass 文檔,編寫一個 Sass 任務 output :

module.exports = function(grunt) {

var sassStyle = ‘expanded’;

grunt.initConfig({
pkg: grunt.file.readJSON(‘package.json’),
sass: {
output : {
options: {
style: sassStyle
},
files: {
‘./style.css’: ‘./scss/style.scss’
}
}
}
});

grunt.loadNpmTasks(‘grunt-contrib-sass’);

grunt.registerTask(‘outputcss’,[‘sass’]);
grunt.registerTask(‘default’);

};
意思就是將 ./scss/style.scss 這個文件以 sassStyle 變量存儲的方式編譯成 根目錄下面的 style.css 文件。

下面拿起命令行,cd 到當前文檔目錄,執行一下 grunt 命令,結果報錯 undefined,沒錯,因爲我們的 default task 裏面沒有定義任何任務,然後執行 grunt outputcss 命令,提示編譯 Scss 文件成功,當然前提是你的 Scss 語法正確,如果有問題就不會成功。

這裏寫圖片描述

下面我們打算先把 src 目錄下面的兩個 JS 文件合併起來,然後再用 jshint 檢測一下是否有語法問題,如果正確,再用 uglify 對合並起來的文件進行壓縮。

參照 grunt-contrib-concat 的官方文檔,我們可以寫出下面的任務:

module.exports = function(grunt) {

var sassStyle = ‘expanded’;

grunt.initConfig({
pkg: grunt.file.readJSON(‘package.json’),
sass: {
output : {
options: {
style: sassStyle
},
files: {
‘./style.css’: ‘./scss/style.scss’
}
}
},
concat: {
options: {
separator: ‘;’,
},
dist: {
src: [‘./src/plugin.js’, ‘./src/plugin2.js’],
dest: ‘./global.js’,
},
}
});

grunt.loadNpmTasks(‘grunt-contrib-sass’);
grunt.loadNpmTasks(‘grunt-contrib-concat’);

grunt.registerTask(‘outputcss’,[‘sass’]);
grunt.registerTask(‘concatjs’,[‘concat’]);
grunt.registerTask(‘default’);

};
執行 grunt concatjs 之後,就會發現根目錄多了一個 global.js 文件,裏面是兩個文件合併起來的。然後類似的繼續看 uglify 和 jshint 的文檔,我們就可以根據需求寫出下面任務:

module.exports = function(grunt) {

var sassStyle = ‘expanded’;

grunt.initConfig({
pkg: grunt.file.readJSON(‘package.json’),
sass: {
output : {
options: {
style: sassStyle
},
files: {
‘./style.css’: ‘./scss/style.scss’
}
}
},
concat: {
options: {
separator: ‘;’,
},
dist: {
src: [‘./src/plugin.js’, ‘./src/plugin2.js’],
dest: ‘./global.js’,
},
},
uglify: {
compressjs: {
files: {
‘./global.min.js’: [‘./global.js’]
}
}
},
jshint: {
all: [‘./global.js’]
}
});

grunt.loadNpmTasks(‘grunt-contrib-sass’);
grunt.loadNpmTasks(‘grunt-contrib-concat’);
grunt.loadNpmTasks(‘grunt-contrib-jshint’);
grunt.loadNpmTasks(‘grunt-contrib-uglify’);

grunt.registerTask(‘outputcss’,[‘sass’]);
grunt.registerTask(‘concatjs’,[‘concat’]);
grunt.registerTask(‘compressjs’,[‘concat’,’jshint’,’uglify’]);
grunt.registerTask(‘default’);

};
其中註冊了一個 compressjs 任務 grunt.registerTask(‘compressjs’,[‘concat’,’jshint’,’uglify’]); 意思就是依次執行 合併、檢查、壓縮 任務。我們把剛生成的 global.js 文件刪掉,在命令行執行 grunt compressjs 任務,結果 jshint 報錯了:
這裏寫圖片描述
grunt jshint 報錯

grunt 遇到錯誤就退出了,就沒法繼續執行下面的任務。通過錯誤提示可以發現,是因爲 concat 裏面設置的參數——在兩個文件合併間插入一個“;”——這本來是爲了防止兩個文件之間相互干擾設置的,結果無法被 jshint 驗證通過,我們可以刪掉這個參數,或者設置 jshint 驗證這兩個文件,然後再進行合併。

爲了方便,我刪掉了這個參數。再執行一下,成功了,項目目錄裏面多了 global.js 和 global.min.js 文件。

小明看到這裏,痛哭流淚,自己每次打開好幾個網站,辛苦挨個粘貼複製新建,沒想到輸入一條命令就可以了。不過讓他更傷心的還在後面,連這些命令都不用重複輸入。

我們可以通過 watch 來監聽文件變動,當文件變化了(我們編寫保存了),自動執行某些任務。此處爲了節約版面,我連自動刷新的任務一塊寫上去。根據 grunt-contrib-watch 和 grunt-contrib-connect 這倆文檔,我們可以寫出下面的任務:

module.exports = function(grunt) {

var sassStyle = ‘expanded’;

grunt.initConfig({
pkg: grunt.file.readJSON(‘package.json’),
sass: {
output : {
options: {
style: sassStyle
},
files: {
‘./style.css’: ‘./scss/style.scss’
}
}
},
concat: {
dist: {
src: [‘./src/plugin.js’, ‘./src/plugin2.js’],
dest: ‘./global.js’,
},
},
uglify: {
compressjs: {
files: {
‘./global.min.js’: [‘./global.js’]
}
}
},
jshint: {
all: [‘./global.js’]
},
watch: {
scripts: {
files: [‘./src/plugin.js’,’./src/plugin2.js’],
tasks: [‘concat’,’jshint’,’uglify’]
},
sass: {
files: [‘./scss/style.scss’],
tasks: [‘sass’]
},
livereload: {
options: {
livereload: ‘<%= connect.options.livereload %>’
},
files: [
‘index.html’,
‘style.css’,
‘js/global.min.js’
]
}
},
connect: {
options: {
port: 9000,
open: true,
livereload: 35729,
// Change this to ‘0.0.0.0’ to access the server from outside
hostname: ‘localhost’
},
server: {
options: {
port: 9001,
base: ‘./’
}
}
}
});

grunt.loadNpmTasks(‘grunt-contrib-sass’);
grunt.loadNpmTasks(‘grunt-contrib-concat’);
grunt.loadNpmTasks(‘grunt-contrib-jshint’);
grunt.loadNpmTasks(‘grunt-contrib-uglify’);
grunt.loadNpmTasks(‘grunt-contrib-watch’);
grunt.loadNpmTasks(‘grunt-contrib-connect’);

grunt.registerTask(‘outputcss’,[‘sass’]);
grunt.registerTask(‘concatjs’,[‘concat’]);
grunt.registerTask(‘compressjs’,[‘concat’,’jshint’,’uglify’]);
grunt.registerTask(‘watchit’,[‘sass’,’concat’,’jshint’,’uglify’,’connect’,’watch’]);
grunt.registerTask(‘default’);

};
添加了 connect 任務,用來新建一個本地服務器,以當前目錄作爲服務器根目錄,然後添加 watch 任務,監聽 Scss 文件變動,如果變了,執行一下 sass 任務,監聽那倆 JS,如果變了,執行 合併、檢查、壓縮 任務,監聽 html、css、js 文件,如果變動,livereload 自動刷新打開的頁面。

而註冊的 watchit task 就是我們的終極 task,第一次執行,先編譯 sass、再合併、檢查、壓縮、開啓服務器、監聽文件變動。我們執行一下 grunt watchit 就可以看到效果了,你可以修改一下 scss 文件,把字體設置大一點,切換到瀏覽器的時候,就看到了實時刷新效果。也可以修改一下 JS,故意改錯一下,會發現 jshint 會提示你出錯了。

grunt watch task

看到這裏,小明和小紅相擁而泣。。。。

項目文件傳輸與協作

項目開發完成之後,往往需要 push 到 Github 或者上傳 FTP 等。或許其他人會接手你的項目繼續開發,或者你會換臺電腦進行開發。

當小明用 git 上傳 Github 的時候,傻了眼,項目裏 node_modules 文件夾下面的東西要十幾M呢,這比我項目本身還大,上傳下載都不方便。

其實這些插件和 grunt 不需要上傳,因爲有 package.json 這個文件記錄了你這個項目中依賴的 grunt 插件,你只需要上傳這個文件即可。下載下來之後,只需要在這個項目文件夾下面,輸入命令 npm install,NPM 會自動讀取 package.json 文件,將 grunt 和有關插件給你下載下來,很方便的。

也不需要在本地上傳的時候刪除,用 git 的話,可以使用 .gitignore 文件來過濾掉這個文件夾,禁止 git 追蹤。

總結與擴展閱讀

Grunt 就是這樣一種任務自動運行器,應用好它可以減輕很多不必要的人工操作,只需要專注 coding 就可以。甚至還有Grunt 插件幫你自動完成 CSS Sprite,更多功能還需要你自己去摸索。

新手看完本文,再看一下 Grunt 官方文檔 應該沒有太多疑問了,那就再看一遍把。當然也有中文版。

除了 Grunt 之外,同類型比較火的還有 Gulp 這個工具。其實兩個東西的功能是一樣的,只不過是任務配置 JS 的語法不同,Gulp 的 Gulpfile.js 的寫法更加通俗易懂,上手更快。但是 Gulp 的插件等感覺不如 Grunt,Grunt 官方提供了一些常見的插件,滿足大部分日常工作,而且可靠值得信賴,而 Gulp 好像沒有太多官方出品,各種插件不太規範。簡單的說,Grunt 和 Gulp 就像 iPhone 與 Android 一樣,一個質量高學習難一點,一個學起來簡單但是有點那個,你懂得。

此外,可以看一些高手的項目,你會發現更好的 Grunt 用法,比如 Yeoman 生成的項目,就有很完善的 Grunt 任務和插件,此外,jQuery 等也用 Grunt 進行打包,這些 Grunt 文件你都可以查看研究一下他們的寫法和用法,受益匪淺。

最後,如果你懶得跟着文章一點點的配置示例項目,你也可以跳轉到示例項目的 grunt 分支,這裏面是我配置好的,你需要先 npm install 然後就可以直接執行那些命令。

發佈了12 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章