gulp vs. grunt

2018-06-09 17:14 更新

GulpGrunt都是用于前端開(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ì)比。

grunt簡(jiǎn)介

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簡(jiǎn)介

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)單輕量呢?

輕量簡(jiǎn)潔的API

gulp的API文檔中有對(duì)其API的詳細(xì)描述??偟膩?lái)說(shuō),gulp原生提供了四個(gè)api接口,

  1. gulp.src(globs[, options]) 指明源文件,所有g(shù)ulp的task都是從讀取源文件開(kāi)始
  2. gulp.dest(path) 指明任務(wù)處理的目標(biāo)輸出路徑
  3. gulp.task(name[, deps], fn) 注冊(cè)任務(wù)
  4. 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)上。

gulp和grunt的差異對(duì)比

在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è)方面,

  1. 配置和運(yùn)行分離
  2. 大部分插件的職責(zé)不單一,做了不僅一件事
  3. 配置項(xiàng)過(guò)多,做的事情越多,配置增長(zhǎng)的就越快,且越不可控制
  4. 任務(wù)執(zhí)行中會(huì)產(chǎn)生一些臨時(shí)文件,較頻繁的IO操作導(dǎo)致性能滯后

我們?cè)賮?lái)看看gulp中是如何解決這些問(wèn)題的,

  1. gulp遵循code over configuration的原則,直接就在調(diào)用的地方配置
  2. gulp的插件嚴(yán)格遵循單一職責(zé)原則,一個(gè)插件僅作一件事,一個(gè)gulp一般只有20多行代碼就搞定
  3. gulp基于流的思想,并沒(méi)有過(guò)多的配置,任務(wù)更多的像是在寫(xiě)代碼而不是定義配置
  4. 這個(gè)是grunt的致命傷,gulp的流式構(gòu)建改變了底層的流程控制,不再頻繁的去進(jìn)行IO操作了

參考列表


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)