1. 程式人生 > >gulp的使用以及Gulp新手入門教程

gulp的使用以及Gulp新手入門教程

Gulp新手入門教程

Gulp 是一個自動化工具,前端開發者可以使用它來處理常見任務:

  • 搭建web伺服器
  • 檔案儲存時自動過載瀏覽器
  • 使用前處理器如Sass、LESS
  • 優化資源,比如壓縮CSS、JavaScript、壓縮圖片

當然Gulp能做的遠不止這些。如果你夠瘋狂,你甚至可以使用它搭建一個靜態頁面生成器。Gulp真的足夠強大,但你必須學會駕馭它。

這是這篇文章的主要目的。幫助你瞭解Gulp的基礎用法,助你早日完成一統天下的大業。

在我們深入瞭解之前,我們先來說說為什麼是Gulp。

為什麼是Gulp?

類似Gulp的工具,我們通常稱之為構建工具。如今最流行的兩個構建工具是Gulp和Grunt。

已經有非常多的文章論證它們之前的異同,你隨便搜一下就知道了。

主要區別是你如何使用他們構建自動化工作流。與Grunt相比,Gulp更加簡潔,執行效率更高。

讓我們繼續學習Gulp並搭建一個簡單的工作流。

我們將要做的

這篇文章的最後,你會擁有簡單的一個工作流:

  • 搭建本地web伺服器
  • 編譯Sass
  • 每當儲存更改,自動重新整理瀏覽器
  • 優化&壓縮資源

除此之外,你還將學會使用簡單命令鏈式呼叫多個任務。

安裝Gulp

安裝Gulp之前你需要先安裝Node.js。

如果你還沒安裝Node,你可以在 這裡 下載。

安裝完Node.js,使用Terminal(終端,win下是cmd)用下面命令安裝Gulp

$ sudo npm install gulp -g

只有mac使用者才需要sudo命令,並且不要把$符號也複製進去,這不是你的菜。

npm install 是指定從Node Package Manager(npm 你怕毛)安裝的命令。

-g 表示全域性安裝,這樣你在電腦上任何位置都能只用gulp 命令。

Mac 使用者需要管理員許可權才能全域性安裝,所以需要sudo。

接下來使用Gulp建立專案。

建立Gulp專案

首先,我們新建一個project資料夾,並在該目錄下執行 npm init 命令:

$ npm init

npm init命令會為你建立一個package.json檔案,這個檔案儲存著這個專案相關資訊。比如你用到的各種依賴(這裡主要是外掛)(終端會自動出現下面內容,這裡先隨便填就行)

建立完之後,我們執行下面的命令:

$ npm install gulp --save-dev

這一次,我們區域性安裝Gulp。使用—save-dev,將通知計算機在package.json中新增gulp依賴。

執行完之後,gulp將建立node_modules資料夾,裡面有個gulp資料夾。

在正式開始之前,我們再來明確下專案的目錄結構。

目錄結構

Gulp非常之靈活,理解它的內部工作,你就能在專案中得心應手。

這篇文章,我們使用通用的webapp目錄結構:

在這個結構中,我們使用app資料夾作為開發目錄(所有的原始檔都放在這下面),dist資料夾用來存放生產環境下的內容。

這些檔名,你想怎麼起都行,但請務必記住你的目錄結構。現在我們來建立gulpfile.js。

第一個Gulp任務

(你需要先在根目錄下建立一個gulpfile.js檔案)。

var gulp = require('gulp');

這行命令告知Node去node_modules中查詢gulp包,先區域性查詢,找不到就去全域性環境中查詢。找到之後就會賦值給gulp變數,然後我們就可以使用它了。

簡單的任務如下所示:

gulp.task('task-name', function() {
  // Stuff here
});

task-name 是給你的任務起的名字,稍後在命令列中執行gulp task-name,將執行該任務。

寫個HelloWorld,是這樣的:

gulp.task('hello', function() {
  console.log('Hello World!');
});

命令列中執行:

$ gulp hello

那麼將會輸出Hello World!。 夠簡單吧?

Gulp任務通常都會比這難一丁點,就一丁點。通常會包含兩個特定的Gulp方法和一些列Gulp外掛。

大概這樣:

gulp.task('task-name', function () {
  return gulp.src('source-files') // Get source files with gulp.src
    .pipe(aGulpPlugin()) // Sends it through a gulp plugin
    .pipe(gulp.dest('destination')) // Outputs the file in the destination folder
})

正如你所見,兩個Gulp方法,src,dest,一進一出[捂臉.jpg]。下面用編譯Sass來舉栗子。

Gulp執行預處理

我們使用gulp-sass外掛來編譯Sass。安裝外掛的步驟是這樣的:

  • 使用npm install 命令安裝

    $ npm install gulp-sass --save-dev
    
  • 在gulpfile中引入外掛,用變數儲存

    var gulp = require('gulp');
    // Requires the gulp-sass plugin
    var sass = require('gulp-sass');
    
  • 在任務中使用

    gulp.task('sass', function(){
      return gulp.src('source-files')
        .pipe(sass()) // Using gulp-sass
        .pipe(gulp.dest('destination'))
    });
    

我們需要給sass任務提供原始檔和輸出位置。所以我們先在專案中建立app/scss資料夾,裡面有個styles.scss檔案。這個檔案將在gulp.src中用到。

sass處理之後,我們希望它生成css檔案併產出到app/css目錄下,可以這樣寫:

gulp.task('sass', function(){
  return gulp.src('app/scss/styles.scss')
    .pipe(sass()) // Converts Sass to CSS with gulp-sass
    .pipe(gulp.dest('app/css'))
});

測試一下:

// styles.scss
.testing {
  width: percentage(5/7);
}

使用Terminal執行gulp sass,你將看到app/css/styles.css檔案下會有下面的程式碼:

/* styles.css */
.testing {
  width: 71.42857%;
}

styles.css是gulp智動為我們生成的。percentage 是Sass的方法。

使用Sass就這麼簡單。但是通常我們不止有一個scss檔案。這時候可以使用Node萬用字元。

Node中的萬用字元

萬用字元是一種匹配模式,允許你匹配到多個檔案。不止是Node,很多平臺都有,有點像正則表示式。

使用萬用字元,計算機檢查檔名和路徑進行匹配。

大部分時候,我們只需要用到下面4種匹配模式:

  1. *.scss : * 號匹配當前目錄任意檔案,所以這裡 *.scss 匹配當前目錄下所有scss檔案
  2. **/*.scss :匹配當前目錄及其子目錄下的所有scss檔案。
  3. !not-me.scss :!號移除匹配的檔案,這裡將移除not-me.scss
  4. *.+(scss|sass) :+號後面會跟著圓括號,裡面的元素用|分割,匹配多個選項。這裡將匹配scss和sass檔案。

那麼還是上面的栗子,改造一下:

gulp.task('sass', function() {
  return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss and children dirs
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
})

任何app下的scss檔案,在執行命令之後將生成對應的css檔案存放到相應路徑。(智動…)

現在我們能處理多個檔案了,但是不想每次都要執行命令,怎麼辦?Gulp就是為懶人而生的,我們可以使用watch命令,自動檢測並執行。

監聽Sass檔案

Gulp提供watch方法給我們,語法如下:

// Gulp watch syntax
gulp.watch('files-to-watch', ['tasks', 'to', 'run']);

將上面的栗子再改下:

// Gulp watch syntax
gulp.watch('app/scss/**/*.scss', ['sass']);

通常我們監聽的還不只是一個檔案,把它變成一個任務:

gulp.task('watch', function(){
  gulp.watch('app/scss/**/*.scss', ['sass']);
  // Other watchers
})

執行gulp watch命令。

有了監聽,每次修改檔案,Gulp都將自動為我們執行任務。

還不夠,修改完直接幫我重新整理瀏覽器行嗎,我不想每次都要手動按Command + R;

使用Browser Sync自動重新整理

Browser Sync 幫助我們搭建簡單的本地伺服器並能實時重新整理瀏覽器,它還能 同時重新整理多個裝置

新外掛?記住!安裝,引入,使用。

$ npm install browser-sync --save-dev

這裡沒有gulp-字首,因為browser-sync支援Gulp,所以沒有人專門去搞一個給Gulp用。

var browserSync = require('browser-sync');

我們建立一個broswerSync任務,我們需要告知它,根目錄在哪裡。

gulp.task('browserSync', function() {
  browserSync({
    server: {
      baseDir: 'app'
    },
  })
})

我們稍微修改一下之前的程式碼,讓每次css檔案更改都重新整理一下瀏覽器:

gulp.task('sass', function() {
  return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
    .pipe(browserSync.reload({
      stream: true
    }))
});

現在我們配置好Broswer Sync了,我們需要執行這兩個命令。

我們可以在watch任務之前告知Gulp,先把browserSync和Sass任務執行了再說。

語法如下:

gulp.task('watch', ['array', 'of', 'tasks', 'to', 'complete','before', 'watch'], function (){
  // ...
})

應用下來是這樣:

gulp.task('watch', ['browserSync', 'sass'], function (){
  gulp.watch('app/scss/**/*.scss', ['sass']);
  // Other watchers
})

現在你執行gulp watch命令,在執行完browserSync和Sass,才會開始監聽。

並且現在瀏覽器的顯示的頁面為app/index.html。你修改了styles.scss之後,瀏覽器將自動屬性頁面。

不止是scss修改的時候需要重新整理瀏覽器吧?再改改:

gulp.task('watch', ['browserSync', 'sass'], function (){
  gulp.watch('app/scss/**/*.scss', ['sass']);
  // Reloads the browser whenever HTML or JS files change
  gulp.watch('app/*.html', browserSync.reload);
  gulp.watch('app/js/**/*.js', browserSync.reload);
});

到目前為止,我們做了下面三件事:

  • 可運轉的web開發服務
  • 使用Sass前處理器
  • 自動重新整理瀏覽器

接下來說說優化方面的技巧

優化CSS和JavaScript檔案

說到優化的時候,我們需要想到:壓縮,拼接。也就是減少體積和HTTP次數。

開發者面臨的主要問題是很難按照正確的順序合併檔案。

<body>
  <!-- other stuff -->
  <script src="js/lib/a-library.js"></script>
  <script src="js/lib/another-library.js"></script>
  <script src="js/main.js"></script>
</body>

gulp-useref會將多個檔案拼接成單一檔案,並輸出到相應目錄。

<!-- build:<type> <path> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->

可以是js,css,或者remove。如果你設為remove,Gulp將不會生成檔案。

指定產出路徑。

我們想最終產出main.min.js。可以這樣寫:

<!--build:js js/main.min.js -->
<script src="js/lib/a-library.js"></script>
<script src="js/lib/another-library.js"></script>
<script src="js/main.js"></script>
<!-- endbuild -->

我們來安裝gulp-useref。

$ npm install gulp-useref --save-dev

引用

var useref = require('gulp-useref');

使用起來非常簡單:

gulp.task('useref', function(){

  return gulp.src('app/*.html')
        .pipe(useref())
        .pipe(gulp.dest('dist'));
});

(新版的gulp-useref已經不需要寫多餘的useref.assets了)

執行useref命令,Gulp將合併三個script標籤成一個檔案,並儲存到dist/js/main.min.js。

合併完之後,我們再來壓縮。使用gulp-uglify外掛。

安裝

$ npm install gulp-uglify --save-dev

使用

// Other requires...
var uglify = require('gulp-uglify');
gulp.task('useref', function(){
  return gulp.src('app/*.html')
    .pipe(uglify()) // Uglifies Javascript files
    .pipe(useref())
    .pipe(gulp.dest('dist'))
});

搞定!

注意:執行完useref後,html中的script路徑將只剩下main.min.js。

王祖藍:完美~

gulp-useref同樣可以用在css上。除了壓縮,需要區分,其它內容同js一樣。所以我們使用gulp-if來做不同處理。

使用gulp-minify-css壓縮css。

$ npm install gulp-if gulp-minify-css --save-dev

應用

var gulpIf = require('gulp-if');
var minifyCSS = require('gulp-minify-css');

gulp.task('useref', function(){

  return gulp.src('app/*.html')
    // Minifies only if it's a CSS file
    .pipe(gulpIf('*.css', minifyCSS()))
    // Uglifies only if it's a Javascript file
    .pipe(gulpIf('*.js', uglify()))
    .pipe(useref())
    .pipe(gulp.dest('dist'))
});

搞定!

再說說如何壓縮圖片。同樣easy。

優化圖片

使用gulp-imagemin外掛。

$ npm install gulp-imagemin --save-dev

引入,使用

var imagemin = require('gulp-imagemin');
gulp.task('images', function(){
  return gulp.src('app/images/**/*.+(png|jpg|gif|svg)')
  .pipe(imagemin())
  .pipe(gulp.dest('dist/images'))
});

(所有的gulp外掛都是有相關引數可以配置,如果需要,請自行檢視。)

壓縮圖片可能會佔用較長時間,使用 gulp-cache 外掛可以減少重複壓縮。

$ npm install gulp-cache --save-dev

引入、使用

var cache = require('gulp-cache');

gulp.task('images', function(){
  return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
  // Caching images that ran through imagemin
  .pipe(cache(imagemin({
      interlaced: true
    })))
  .pipe(gulp.dest('dist/images'))
});

接下來,我們說說釋出流程。

清理生成檔案

由於我們是自動生成檔案,我們不想舊檔案摻雜進來。

使用 del

npm install del --save-dev

引入、使用

var del = require('del');
gulp.task('clean', function() {
  del('dist');
});

但是我們又不想圖片被刪除(圖片改動的機率不大),啟用新的任務。

gulp.task('clean:dist', function(callback){
  del(['dist/**/*', '!dist/images', '!dist/images/**/*'], callback)
});

這個任務會刪除,除了images/資料夾,dist下的任意檔案。為了知道clean:dist任務什麼時候完成,我們需要提供callback引數。

在某些時候我們還是需要清除圖片,所以clean任務我們還需要保留。

gulp.task('clean', function(callback) {
  del('dist');
  return cache.clearAll(callback);
})

噢,我真的是廢話太多了。把我們學到的組合到一塊吧!

組合Gulp任務

廢話了這麼多,我們主要有兩條線路。

第一條是開發過程,我們便以Sass,監聽檔案,重新整理瀏覽器。

第二條是優化,我們優化CSS,JavaScript,壓縮圖片,並把資源從app移動到dist。

開發任務我們上面的watch已經組裝好了。

gulp.task('watch', ['browserSync', 'sass'], function (){
  // ... watchers
})

我們也做一個來執行第二條線路。

gulp.task('build', [`clean`, `sass`, `useref`, `images`, `fonts`], function (){
  console.log('Building files');
})

但是這樣Gulp會同時觸發 [] 的事件。我們要讓clean在其他任務之前完成。

$ npm install run-sequence --save-dev

用法如下:

var runSequence = require('run-sequence');

gulp.task('task-name', function(callback) {
  runSequence('task-one', 'task-two', 'task-three', callback);
});

執行task-name時,Gulp會按照順序執行task-one,task-two,task-thre。

RunSequence也允許你同時執行多個任務。

gulp.task('task-name', function(callback) {
  runSequence('task-one', ['tasks','two','run','in','parallel'], 'task-three', callback);
});

改造我們的程式碼:

gulp.task('build', function (callback) {
  runSequence('clean:dist',
    ['sass', 'useref', 'images', 'fonts'],
    callback
  )
})

開發任務我們也用runSequence:

gulp.task('default', function (callback) {
  runSequence(['sass','browserSync', 'watch'],
    callback
  )
})

default? 如果你的任務名字叫做default,那麼只需要輸入gulp命令即可執行。

這裡是我們最終的 程式碼倉庫 。

總結

上面的的內容搭建了一個基本的Gulp工作流。還有更精彩的內容等著你去開發。這裡提供些外掛:

開發過程:

優化:

  • unCSS 移除多餘的CSS
  • CSSO 更深入地優化CSS

除了開發和優化過程,你可以使用gulp-jasmine寫JavaScript單元測試,甚至使用gulp-rync直接部署dist檔案到生產環境。

譯者的話

花了點時間去學習Gulp,這篇文章是我找到比較全面的,非常適合新手入門。

Gulp其實非常簡單,多玩一下,你就能完全掌握它了,有能力的話,可以嘗試開發Gulp外掛。