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