Gulp和Grunt都是用于前端開發(fā)的構(gòu)建工具(或者說它們是任務(wù)運行管理器更加合適一點)。其中Grunt的出現(xiàn)要比Gulp早不少時間,不過Gulp后來居上隱隱有取而代之的態(tài)勢。
下面我將會對grunt及gulp先做一個簡單的用法介紹,不過會著重介紹下gulp,最后再簡單的將兩者做一個對比。
gruntjs中文社區(qū)介紹grunt是這么說的,JavaScript世界的構(gòu)建工具。
其實構(gòu)建工具基本上就是讓一些重復(fù)的任務(wù)自動化。我們先來上一個簡單使用grunt的例子來大概了解下grunt是怎么用的。
首先是安裝,grunt有一個對應(yīng)的grunt-cli,我們需要全局安裝這個cli,
~ npm install -g grunt-cli
然后切換到項目目錄,安裝grunt及用到的插件,因為是僅作示例,我這里就使用了一個插件。
~ cd <YOUR_PROJECT_DIR>
~ npm install gulp grunt-contrib-uglify --save-dev
然后創(chuàng)建Gruntfile.js
文件,其內(nèi)容如下,
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/*.js',
dest: 'build/all.min.js'
}
}
});
// 加載包含 "uglify" 任務(wù)的插件。
grunt.loadNpmTasks('grunt-contrib-uglify');
// 默認(rèn)被執(zhí)行的任務(wù)列表。
grunt.registerTask('default', ['uglify']);
};
從Gruntfile.js文件中可以看出文件內(nèi)容主要分為兩塊,第一塊是相關(guān)task的配置,第二塊是加載任務(wù)。
本示例中,我僅僅配置了一個叫做uglify
的任務(wù),用于壓縮代碼文件。具體的策略是:壓縮src目錄下的所有js文件,然后將壓縮好的文件合并在一起輸入到dest目錄下的all.min.js文件中。(這里可以看出,這個uglify插件除了壓縮之外還做了合并的事。)
結(jié)果如下,
Running "uglify:build" (uglify) task
>> 1 file created.
Done, without errors.
更多的內(nèi)容,請參考grunt的官方文檔。
gulp是一款開源的基于流的構(gòu)建工具,托管在github上,地址在這里,目前已經(jīng)有10000+個Star,相比grunt的近9000個Star,后來居上,發(fā)展勢頭很迅猛。
下面我們通過一個簡單的例子來領(lǐng)略下gulp的風(fēng)采。
首先是安裝,下面的兩種方式可以根據(jù)你的喜好和情況自由選擇,
~ npm install -g gulp
~ cd <YOUR_PROJECT_DIR>
~ npm install gulp --save-dev
然后是在項目的根目錄下創(chuàng)建Gulpfile.js
文件,
var gulp = require('gulp');
uglify = require('gulp-uglify'),
concat = require('gulp-concat');
gulp.task('default', function () {
return gulp.src('./src/*.js')
.pipe(uglify())
.pipe(concat('all.min.js'))
.pipe(gulp.dest('./build'));
});
最后就可以運行了,
~ gulp
結(jié)果如下,
[14:14:13] Using gulpfile D:\WebstormProjects\hello-gulp\gulpfile.js
[14:14:13] Starting 'default'...
[14:14:13] Finished 'default' after 37 ms
啊哈,是不是很簡單輕量呢?
gulp的API文檔中有對其API的詳細(xì)描述??偟膩碚f,gulp原生提供了四個api接口,
gulp.src(globs[, options])
指明源文件,所有g(shù)ulp的task都是從讀取源文件開始gulp.dest(path)
指明任務(wù)處理的目標(biāo)輸出路徑gulp.task(name[, deps], fn)
注冊任務(wù)gulp.watch
監(jiān)視文件改動并運行相關(guān)邏輯或者任務(wù)我們使用gulp來完成以下三個構(gòu)建任務(wù):1.語法檢查(gulp-jshint),2.合并文件(gulp-concat),3.壓縮代碼(gulp-uglify)。完整的代碼如下,
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
// 語法檢查
gulp.task('jshint', function () {
return gulp.src('src/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
// 合并文件之后壓縮代碼
gulp.task('minify', function () {
return gulp.src('src/*.js')
.pipe(concat('all.js'))
.pipe(gulp.dest('dist'))
.pipe(uglify())
.pipe(rename('all.min.js'))
.pipe(gulp.dest('dist'));
});
// 監(jiān)視文件的變化
gulp.task('watch', function () {
gulp.watch('src/*.js', ['jshint', 'minify']);
});
// 注冊缺省任務(wù)
gulp.task('default', ['jshint', 'minify', 'watch']);
除了watch
任務(wù)外,基本上所有的任務(wù)單元都是這么樣的一個模式,
gulp.task('task-name', function () {
var stream = gulp.src('...') // 流開始
.pipe(...)
.pipe(...)
// 任務(wù)的最后一步
.pipe(...);
return stream;
});
所以,為什么說gulp是一種基于流的構(gòu)建工具,從這里可以看出,每個任務(wù)從src
讀取源文件生成流開始,中間通過pipe
傳遞流,所有的任務(wù)步驟都是在流上做一些操作,最后將流通過dest
輸出到目標(biāo)上。
在github上有相當(dāng)一些項目是用grunt作為構(gòu)建工具的,觀察這些項目的Gruntfile.js文件,可以很容易發(fā)現(xiàn)大部分的Gruntfile.js都非常臃腫,有一大段一大段的嵌套配置結(jié)構(gòu),令人看起來很煩躁。這些冗余的Gruntfile.js
文件其實維護(hù)起來并不是那么輕量的,主要體現(xiàn)在下面幾個方面,
我們再來看看gulp中是如何解決這些問題的,
更多建議: