是時候擱置Grunt,耍一耍gulp了

來源:互聯網
上載者:User

標籤:des   style   blog   http   ar   io   color   os   使用   

也算是用了半年Grunt,幾個月前也寫過一篇它的入門文章(點此查看),不得不說它是前端項目的一個得力助手。不過技術工具跟語言一樣日新月異,總會有更好用的新的東西把舊的拍死在沙灘上(當然Grunt肯定沒死,gulp也不是多新穎的東西)。

看標題很明顯知道相比Grunt,我會更為推崇gulp,不是說Grunt不好,而是gulp效率更高、健壯性更好,配置也更為簡單,自然也值得我們為它任性一回。

先談談上述提到的gulp的優越性:

一. 效能更高

相對Grunt頻繁的IO操作讀寫,gulp是將專案工作流程以streaming(流)的形式來做管道化處理,這句話怎麼理解呢?

比如一個檔案A,Grunt按順序會有三個組件任務a、b、c 要對起進行處理,那麼流程可能是這樣的:

讀取A → A.a() → 寫A  → 讀取A → A.b() → 寫A  → 讀取A → A.c() → 寫A  → complete/watch...

那麼換成gulp又是怎樣的一個過程,它大概是這麼處理:

讀取A並轉為流資訊 → A.a() → A.b()  → A.c() → 寫A  → complete/watch...

可以看到執行任務的過程,是減少了(3-1)處對檔案A的讀/寫操作,減輕了磁碟IO操作負擔,效率自然也得到明顯提升。

至於“流”的概念,可以戳這裡瞭解一下。大致是讀取檔案時,不按常規那樣把檔案一口氣寫入記憶體中,而是把檔案轉為資料流,收到多少資料就處理多少資料,像經過竹筒的涓涓流水那樣,有水源過來了就馬上處理後(你可以假設竹筒在這裡有淨水的過濾作用)再送出去,直到水源全部“流”過該竹筒。

那麼“管道化”處理又是怎樣的概念?

它很類似jQuery中的鏈式寫法,在nodeJS中管道式方法的api一般為.pipe() ,比如

XXXX.pipe(a())  //處理a任務     .pipe(b())  //處理b任務     .pipe(c())  //處理c任務

你也可以理解為上述的涓涓流水經過一排竹筒後,緊接著流向下一個竹筒,一直這樣迴圈,直到流過最後一個竹筒(當然流水依舊代表資料,竹筒代表任務)。

 

二. 健壯性更好

gulp走的是遞迴編譯的解析方式,有助於項目最佳化的健壯性。打個比方,比如我們使用sass來編寫樣式,其中b.scss引入了_a.scss檔案,如果我們修改了_a.scss的內容,gulp會即時更新b.scss對應的b.css編譯檔案,但Grunt是基於緩衝機制的,故不會重新編譯b.scss檔案,導致問題。

 

三. 配置更簡潔

其實之前寫的那篇Grunt入門的文章,我的確不懂到底要如何介紹Gruntfile.js的配置——略複雜和混亂,鄙人口才也不好,便草草幾句話帶過,相信讀者可能也不太能夠理清頭緒。另外Gruntfile.js中已經寫明了任務所依賴的組件,但還要多此一舉配置一份package.json也是匪夷所思。

相比之下,gulp好太多了,只需要一份 gulpfile.js 即可,而且多虧了gulp的流式管道化處理,起配置寫法也算簡潔、統一了許多

為你的項目搭建gulp任務

搭建gulp其實很簡單,就倆步驟——在項目根目錄下安裝所需組件,並配置一份gulpfile.js。

我們假設我們有一個放在D盤下的項目 D:/project,裡面的檔案結構是這樣的:

我們打算利用gulp把RAW檔案夾下的js和sass檔案編譯/壓縮後都輸出到COMPRESS檔案夾下。

 

一. 安裝組件

gulp自己有官方的組件推薦/尋找頁面(點我進入),就我們上述項目要求而言,我個人推薦下述幾個組件:

  gulp   //這個是必須安裝的,沒有它,其它組件都用不了(注意watch組件直接整合在gulp中了,無需額外安裝watch組件)
  gulp-sass    //編譯sass用的
  gulp-sourcemaps    //編譯sass時產生額外的.map檔案用的(有啥用?看我這篇文章)
  gulp-mini-css    //壓縮css使用的
  gulp-uglify    //壓縮、混淆js檔案用的

組件的安裝很簡單,直接npm安裝即可,比如安裝gulp:

npm install gulp

安裝過程可能會遇到組件被牆導致串連不上鏡像的問題,解決方案有兩個,一個是FQ,另一個是走cnpm鏡像(點此查閱)。

組件全部安裝完成後會在你的項目根目錄下產生一個node_modules檔案夾,用來存放組件模組:

 

二. gulpfile.js檔案配置

如同Grunt需要配置Gruntfile.js檔案來告知node我要用什麼組件並以怎樣的流程來執行任務,gulp也需要在項目根目錄配置一個gulpfile.js檔案。
我們建立一個gulpfile.js檔案,先在之中輸入下面內容:

var gulp = require(‘gulp‘),    sass = require(‘gulp-sass‘),    mincss = require(‘gulp-mini-css‘),    sourcemaps = require(‘gulp-sourcemaps‘),    uglify = require(‘gulp-uglify‘);

濃濃的commonJS風,告知node我們要使用哪些組件模組來完成任務。
接著我們進一步設定檔,告訴node我們具體要以怎樣的流程來執行任務,這是完整的gulpfile.js檔案內容:

var gulp = require(‘gulp‘),    sass = require(‘gulp-sass‘),    mincss = require(‘gulp-mini-css‘),    sourcemaps = require(‘gulp-sourcemaps‘),    uglify = require(‘gulp-uglify‘);var raw_css = ‘./RAW/css‘,    com_css = ‘./COMPRESS/css‘,    raw_js = ‘./RAW/js‘,    com_js = ‘./COMPRESS/js‘;gulp.task(‘sass‘, function () {    gulp.src(raw_css+‘/**/*.scss‘)        .pipe(sourcemaps.init())        .pipe(sass())        .pipe(sourcemaps.write(‘/‘))        .pipe(mincss())        .pipe(gulp.dest(com_css));});gulp.task(‘mincss‘, function () {    gulp.src(com_css+‘/**/*.scss‘)        .pipe(mincss())        .pipe(gulp.dest(com_css));});gulp.task(‘minjs‘, function () {    gulp.src(raw_js+‘/**/*.js‘)        .pipe(uglify())        .pipe(gulp.dest(com_js));});gulp.task(‘watch‘, function () {    gulp.watch(raw_css+‘/**/*.scss‘,[‘sass‘]);    gulp.watch(raw_js+‘/**/*.js‘,[‘minjs‘]);});gulp.task(‘default‘,function(){    gulp.run(‘sass‘,‘minjs‘,‘mincss‘);    gulp.run(‘watch‘);});

我們拿寫的最長的sass編譯模組配置代碼塊來注釋說明下:

//每個gulp.task(name, fn)都是一個任務配置模組,如本程式碼片段定義了名為"sass"的任務的執行流程gulp.task(‘sass‘, function () {        gulp.src(raw_css+‘/**/*.scss‘)   //gulp.src(glob)返回了一個可讀的stream,如此行返回了RAW/css/下的全部(包含子檔案夾裡的).scss檔案流        .pipe(sourcemaps.init())  //.pipe()管道化動作項目任務,此處調用gulp-sourcemaps的初始化api來處理接收的檔案流(方便後續編譯出.map檔案)        .pipe(sass())         //執行gulp-sass組件任務,把.scss檔案流編譯為.css檔案流        .pipe(sourcemaps.write(‘/‘))      //調用gulp-sourcemaps的寫入api,額外輸出.map檔案流        .pipe(mincss())     //執行gulp-mini-css組件任務,壓縮所有css檔案流        .pipe(gulp.dest(com_css));   //gulp.dest(glob)返回一個可寫的stream,如此行是將檔案流寫入到 COMPRESS/css 裡的對應路徑下});

 接著看看末尾處的兩個程式碼片段:

gulp.task(‘watch‘, function () {  //定義名為"watch"的任務    gulp.watch(raw_css+‘/**/*.scss‘,[‘sass‘]);   //監聽 RAW/css 下的全部.scss檔案,若有改動則執行名為‘sass‘任務    gulp.watch(raw_js+‘/**/*.js‘,[‘minjs‘]);   //監聽 RAW/js 下的全部.js檔案,若有改動則執行名為‘minjs‘任務});gulp.task(‘default‘,function(){  //每個gulpfile.js裡都應當有一個dafault任務,它是預設任務入口(類似C語言的main()入口),運行gulp的時候實際只是調用該任務(從而來調用其它的任務)    gulp.run(‘sass‘,‘minjs‘,‘mincss‘);   //gulp.run(tasks)表示運行對應的任務,這裡表示執行名為‘sass‘,‘minjs‘,‘mincss‘的三個任務    gulp.run(‘watch‘);    //執行‘watch‘監聽任務});

上述的兩個步驟做好後,直接輸入運行 gulp 指令即可(我是在webstorm裡直接寫命令的):

同時可以看到COMPRESS檔案夾下已經有了我們想要的編譯、壓縮後的檔案:

另外這時候gulp已轉入監聽模式(雖然不像Grunt那樣有“watch...”的提示),只要你修改了被監聽的檔案,任務會立即被執行一遍,無需再手動gulp一次。

用下來還是覺得gulp是個好東西,比Grunt更易上手,效率也更好,不過相較Grunt的“grunt-newer”組件,gulp對應功能的兩個組件“gulp-changed”和"gulp-newer"貌似運行起來都達不到預想效果,比如我希望只針對我修改了的某個sass檔案來做任務處理,我做了如下配置:

var gulp = require(‘gulp‘),    sass = require(‘gulp-sass‘),    mincss = require(‘gulp-mini-css‘),    sourcemaps = require(‘gulp-sourcemaps‘),    changed = require(‘gulp-changed‘),    uglify = require(‘gulp-uglify‘);var raw_css = ‘./RAW/css‘,    com_css = ‘./COMPRESS/css‘,    raw_js = ‘./RAW/js‘,    com_js = ‘./COMPRESS/js‘;gulp.task(‘sass‘, function () {    gulp.src(raw_css+‘/*.scss‘)        .pipe(changed(raw_css+‘/*.scss‘))        .pipe(sourcemaps.init())        .pipe(sass())        .pipe(sourcemaps.write(‘/‘))        .pipe(mincss())        .pipe(gulp.dest(com_css));});gulp.task(‘mincss‘, function () {    gulp.src(com_css+‘/*.scss‘)        .pipe(changed(com_css))        .pipe(mincss())        .pipe(gulp.dest(com_css));});gulp.task(‘minjs‘, function () {    gulp.src(raw_js+‘/*.js‘)        .pipe(changed(com_js))        .pipe(uglify())        .pipe(gulp.dest(com_js));});gulp.task(‘watch‘, function () {    gulp.watch(raw_css+‘/*.scss‘,[‘sass‘]);    gulp.watch(raw_js+‘/*.js‘,[‘minjs‘]);});gulp.task(‘default‘,function(){    gulp.run(‘sass‘,‘minjs‘,‘mincss‘);    gulp.run(‘watch‘);});
View Code

結果發現依舊是整個檔案夾下的檔案都被做了任務處理。或許是我的配置不正確,若有瞭解newer或者changed的朋友望能不吝指正。

另外百度fis貌似也是另一個不錯的alternative,跟gulp差不多,而且中文文檔也挺詳細的,之前用過百度的一些東西,感覺品質還是有保障的。

最後推薦下一個大神級朋友的部落格,在我們苦口婆心的催產下他終於發表了第一篇文章,介紹的JS物件導向的思想,歡迎大家去看一看。

共勉~

是時候擱置Grunt,耍一耍gulp了

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.