1. 程式人生 > >Gulp自動管理工具的入門和技巧

Gulp自動管理工具的入門和技巧

gulpjs是一個前端構建工具,與gruntjs相比,gulpjs無需寫一大堆繁雜的配置引數,API也非常簡單,學習起來很容易,而且gulpjs使用的是nodejs中stream來讀取和操作資料,其速度更快。如果你還沒有使用過前端構建工具,或者覺得gruntjs太難用的話,那就嘗試一下gulp吧。

本文導航:

1、gulp的安裝

首先確保你已經正確安裝了nodejs環境。然後以全域性方式安裝gulp:

npm install -g gulp

全域性安裝gulp後,還需要在每個要使用gulp的專案中都單獨安裝一次。把目錄切換到你的專案資料夾中,然後在命令列中執行:

npm install gulp

如果想在安裝的時候把gulp寫進專案package.json檔案的依賴中,則可以加上--save-dev:

npm install --save-dev gulp

2、開始使用gulp

2.1 建立gulpfile.js檔案

就像gruntjs需要一個Gruntfile.js檔案一樣,gulp也需要一個檔案作為它的主檔案,在gulp中這個檔案叫做gulpfile.js。新建一個檔名為gulpfile.js的檔案,然後放到你的專案目錄中。之後要做的事情就是在gulpfile.js檔案中定義我們的任務了。下面是一個最簡單的gulpfile.js檔案內容示例,它定義了一個預設的任務。

var
gulp = require('gulp'); gulp.task('default',function(){ console.log('hello world'); });

此時我們的目錄結構是這樣子的:

├── gulpfile.js
├── node_modules
│ └── gulp
└── package.json

2.2 執行gulp任務

要執行gulp任務,只需切換到存放gulpfile.js檔案的目錄(windows平臺請使用cmd或者Power Shell等工具),然後在命令列中執行gulp命令就行了,gulp後面可以加上要執行的任務名,例如gulp task1

,如果沒有指定任務名,則會執行任務名為default的預設任務。

3、gulp的API介紹

使用gulp,僅需知道4個API即可:gulp.task(),gulp.src(),gulp.dest(),gulp.watch(),所以很容易就能掌握,但有幾個地方需理解透徹才行,我會在下面一一說明。為了避免出現理解偏差,建議先看一遍官方文件

3.1 gulp.src()

在介紹這個API之前我們首先來說一下Grunt.js和Gulp.js工作方式的一個區別。Grunt主要是以檔案為媒介來執行它的工作流的,比如在Grunt中執行完一項任務後,會把結果寫入到一個臨時檔案中,然後可以在這個臨時檔案內容的基礎上執行其它任務,執行完成後又把結果寫入到臨時檔案中,然後又以這個為基礎繼續執行其它任務...就這樣反覆下去。而在Gulp中,使用的是Nodejs中的stream(流),首先獲取到需要的stream,然後可以通過stream的pipe()方法把流匯入到你想要的地方,比如Gulp的外掛中,經過外掛處理後的流又可以繼續匯入到其他外掛中,當然也可以把流寫入到檔案中。所以Gulp是以stream為媒介的,它不需要頻繁的生成臨時檔案,這也是Gulp的速度比Grunt快的一個原因。再回到正題上來,gulp.src()方法正是用來獲取流的,但要注意這個流裡的內容不是原始的檔案流,而是一個虛擬檔案物件流(Vinyl files),這個虛擬檔案物件中儲存著原始檔案的路徑、檔名、內容等資訊,這個我們暫時不用去深入理解,你只需簡單的理解可以用這個方法來讀取你需要操作的檔案就行了。其語法為:

gulp.src(globs[, options])

globs引數是檔案匹配模式(類似正則表示式),用來匹配檔案路徑(包括檔名),當然這裡也可以直接指定某個具體的檔案路徑。當有多個匹配模式時,該引數可以為一個數組。
options為可選引數。通常情況下我們不需要用到。

下面我們重點說說Gulp用到的glob的匹配規則以及一些檔案匹配技巧。
Gulp內部使用了node-glob模組來實現其檔案匹配功能。我們可以使用下面這些特殊的字元來匹配我們想要的檔案:

  • * 匹配檔案路徑中的0個或多個字元,但不會匹配路徑分隔符,除非路徑分隔符出現在末尾
  • ** 匹配路徑中的0個或多個目錄及其子目錄,需要單獨出現,即它左右不能有其他東西了。如果出現在末尾,也能匹配檔案。
  • ? 匹配檔案路徑中的一個字元(不會匹配路徑分隔符)
  • [...] 匹配方括號中出現的字元中的任意一個,當方括號中第一個字元為^!時,則表示不匹配方括號中出現的其他字元中的任意一個,類似js正則表示式中的用法
  • !(pattern|pattern|pattern) 匹配任何與括號中給定的任一模式都不匹配的
  • ?(pattern|pattern|pattern) 匹配括號中給定的任一模式0次或1次,類似於js正則中的(pattern|pattern|pattern)?
  • +(pattern|pattern|pattern) 匹配括號中給定的任一模式至少1次,類似於js正則中的(pattern|pattern|pattern)+
  • *(pattern|pattern|pattern) 匹配括號中給定的任一模式0次或多次,類似於js正則中的(pattern|pattern|pattern)*
  • @(pattern|pattern|pattern) 匹配括號中給定的任一模式1次,類似於js正則中的(pattern|pattern|pattern)

下面以一系列例子來加深理解

  • * 能匹配 a.js,x.y,abc,abc/,但不能匹配a/b.js
  • *.* 能匹配 a.js,style.css,a.b,x.y
  • */*/*.js 能匹配 a/b/c.js,x/y/z.js,不能匹配a/b.js,a/b/c/d.js
  • ** 能匹配 abc,a/b.js,a/b/c.js,x/y/z,x/y/z/a.b,能用來匹配所有的目錄和檔案
  • **/*.js 能匹配 foo.js,a/foo.js,a/b/foo.js,a/b/c/foo.js
  • a/**/z 能匹配 a/z,a/b/z,a/b/c/z,a/d/g/h/j/k/z
  • a/**b/z 能匹配 a/b/z,a/sb/z,但不能匹配a/x/sb/z,因為只有單**單獨出現才能匹配多級目錄
  • ?.js 能匹配 a.js,b.js,c.js
  • a?? 能匹配 a.b,abc,但不能匹配ab/,因為它不會匹配路徑分隔符
  • [xyz].js 只能匹配 x.js,y.js,z.js,不會匹配xy.js,xyz.js等,整個中括號只代表一個字元
  • [^xyz].js 能匹配 a.js,b.js,c.js等,不能匹配x.js,y.js,z.js

當有多種匹配模式時可以使用陣列

//使用陣列的方式來匹配多種檔案
gulp.src(['js/*.js','css/*.css','*.html'])

使用陣列的方式還有一個好處就是可以很方便的使用排除模式,在陣列中的單個匹配模式前加上!即是排除模式,它會在匹配的結果中排除這個匹配,要注意一點的是不能在陣列中的第一個元素中使用排除模式

gulp.src([*.js,'!b*.js']) //匹配所有js檔案,但排除掉以b開頭的js檔案
gulp.src(['!b*.js',*.js]) //不會排除任何檔案,因為排除模式不能出現在陣列的第一個元素中

此外,還可以使用展開模式。展開模式以花括號作為定界符,根據它裡面的內容,會展開為多個模式,最後匹配的結果為所有展開的模式相加起來得到的結果。展開的例子如下:

  • a{b,c}d 會展開為 abd,acd
  • a{b,}c 會展開為 abc,ac
  • a{0..3}d 會展開為 a0d,a1d,a2d,a3d
  • a{b,c{d,e}f}g 會展開為 abg,acdfg,acefg
  • a{b,c}d{e,f}g 會展開為 abdeg,acdeg,abdeg,abdfg

3.2 gulp.dest()

gulp.dest()方法是用來寫檔案的,其語法為:

gulp.dest(path[,options])

path為寫入檔案的路徑
options為一個可選的引數物件,通常我們不需要用到

要想使用好gulp.dest()這個方法,就要理解給它傳入的路徑引數與最終生成的檔案的關係。
gulp的使用流程一般是這樣子的:首先通過gulp.src()方法獲取到我們想要處理的檔案流,然後把檔案流通過pipe方法匯入到gulp的外掛中,最後把經過外掛處理後的流再通過pipe方法匯入到gulp.dest()中,gulp.dest()方法則把流中的內容寫入到檔案中,這裡首先需要弄清楚的一點是,我們給gulp.dest()傳入的路徑引數,只能用來指定要生成的檔案的目錄,而不能指定生成檔案的檔名,它生成檔案的檔名使用的是匯入到它的檔案流自身的檔名,所以生成的檔名是由匯入到它的檔案流決定的,即使我們給它傳入一個帶有檔名的路徑引數,然後它也會把這個檔名當做是目錄名,例如:

var gulp = require('gulp');
gulp.src('script/jquery.js')
    .pipe(gulp.dest('dist/foo.js'));
//最終生成的檔案路徑為 dist/foo.js/jquery.js,而不是dist/foo.js

下面說說生成的檔案路徑與我們給gulp.dest()方法傳入的路徑引數之間的關係。
gulp.dest(path)生成的檔案路徑是我們傳入的path引數後面再加上gulp.src()中有萬用字元開始出現的那部分路徑。例如:

var gulp = reruire('gulp');
//有萬用字元開始出現的那部分路徑為 **/*.js
gulp.src('script/**/*.js')
    .pipe(gulp.dest('dist')); //最後生成的檔案路徑為 dist/**/*.js
//如果 **/*.js 匹配到的檔案為 jquery/jquery.js ,則生成的檔案路徑為 dist/jquery/jquery.js

再舉更多一點的例子

gulp.src('script/avalon/avalon.js') //沒有萬用字元出現的情況
    .pipe(gulp.dest('dist')); //最後生成的檔案路徑為 dist/avalon.js

//有萬用字元開始出現的那部分路徑為 **/underscore.js
gulp.src('script/**/underscore.js')
    //假設匹配到的檔案為script/util/underscore.js
    .pipe(gulp.dest('dist')); //則最後生成的檔案路徑為 dist/util/underscore.js

gulp.src('script/*') //有萬用字元出現的那部分路徑為 *
    //假設匹配到的檔案為script/zepto.js    
    .pipe(gulp.dest('dist')); //則最後生成的檔案路徑為 dist/zepto.js

通過指定gulp.src()方法配置引數中的base屬性,我們可以更靈活的來改變gulp.dest()生成的檔案路徑。
當我們沒有在gulp.src()方法中配置base屬性時,base的預設值為萬用字元開始出現之前那部分路徑,例如:

gulp.src('app/src/**/*.css') //此時base的值為 app/src

上面我們說的gulp.dest()所生成的檔案路徑的規則,其實也可以理解成,用我們給gulp.dest()傳入的路徑替換掉gulp.src()中的base路徑,最終得到生成檔案的路徑。

gulp.src('app/src/**/*.css') //此時base的值為app/src,也就是說它的base路徑為app/src
     //設該模式匹配到了檔案 app/src/css/normal.css
    .pipe(gulp.dest('dist')) //用dist替換掉base路徑,最終得到 dist/css/normal.css

所以改變base路徑後,gulp.dest()生成的檔案路徑也會改變

gulp.src(script/lib/*.js) //沒有配置base引數,此時預設的base路徑為script/lib
    //假設匹配到的檔案為script/lib/jquery.js
    .pipe(gulp.dest('build')) //生成的檔案路徑為 build/jquery.js

gulp.src(script/lib/*.js, {base:'script'}) //配置了base引數,此時base路徑為script
    //假設匹配到的檔案為script/lib/jquery.js
    .pipe(gulp.dest('build')) //此時生成的檔案路徑為 build/lib/jquery.js    

gulp.dest()把檔案流寫入檔案後,檔案流仍然可以繼續使用。

3.3 gulp.task()

gulp.task方法用來定義任務,內部使用的是Orchestrator,其語法為:

gulp.task(name[, deps], fn)

name 為任務名
deps 是當前定義的任務需要依賴的其他任務,為一個數組。當前定義的任務會在所有依賴的任務執行完畢後才開始執行。如果沒有依賴,則可省略這個引數
fn 為任務函式,我們把任務要執行的程式碼都寫在裡面。該引數也是可選的。

gulp.task('mytask', ['array', 'of', 'task', 'names'], function() { //定義一個有依賴的任務
  // Do something
});

gulp.task()這個API沒什麼好講的,但需要知道執行多個任務時怎麼來控制任務執行的順序。
gulp中執行多個任務,可以通過任務依賴來實現。例如我想要執行one,two,three這三個任務,那我們就可以定義一個空的任務,然後把那三個任務當做這個空的任務的依賴就行了:

//只要執行default任務,就相當於把one,two,three這三個任務執行了
gulp.task('default',['one','two','three']);

如果任務相互之間沒有依賴,任務會按你書寫的順序來執行,如果有依賴的話則會先執行依賴的任務。
但是如果某個任務所依賴的任務是非同步的,就要注意了,gulp並不會等待那個所依賴的非同步任務完成,而是會接著執行後續的任務。例如:

gulp.task('one',function(){
  //one是一個非同步執行的任務
  setTimeout(function(){
    console.log('one is done')
  },5000);
});

//two任務雖然依賴於one任務,但並不會等到one任務中的非同步操作完成後再執行
gulp.task('two',['one'],function(){
  console.log('two is done');
});

上面的例子中我們執行two任務時,會先執行one任務,但不會去等待one任務中的非同步操作完成後再執行two任務,而是緊接著執行two任務。所以two任務會在one任務中的非同步操作完成之前就執行了。

那如果我們想等待非同步任務中的非同步操作完成後再執行後續的任務,該怎麼做呢?
有三種方法可以實現:
第一:在非同步操作完成後執行一個回撥函式來通知gulp這個非同步任務已經完成,這個回撥函式就是任務函式的第一個引數。

gulp.task('one',function(cb){ //cb為任務函式提供的回撥,用來通知任務已經完成
  //one是一個非同步執行的任務
  setTimeout(function(){
    console.log('one is done');
    cb();  //執行回撥,表示這個非同步任務已經完成
  },5000);
});

//這時two任務會在one任務中的非同步操作完成後再執行
gulp.task('two',['one'],function(){
  console.log('two is done');
});

第二:定義任務時返回一個流物件。適用於任務就是操作gulp.src獲取到的流的情況。

gulp.task('one',function(cb){
  var stream = gulp.src('client/**/*.js')
      .pipe(dosomething()) //dosomething()中有某些非同步操作
      .pipe(gulp.dest('build'));
    return stream;
});

gulp.task('two',['one'],function(){
  console.log('two is done');
});

第三:返回一個promise物件,例如

var Q = require('q'); //一個著名的非同步處理的庫 https://github.com/kriskowal/q
gulp.task('one',function(cb){
  
            
           

相關推薦

Gulp自動管理工具入門技巧

gulpjs是一個前端構建工具,與gruntjs相比,gulpjs無需寫一大堆繁雜的配置引數,API也非常簡單,學習起來很容易,而且gulpjs使用的是nodejs中stream來讀取和操作資料,其速度更快。如果你還沒有使用過前端構建工具,或者覺得gruntjs太難用的話,那就嘗試一下gulp吧。 本文導航

xcode第三方庫自動下載管理工具cocoapodsCarthage

程式碼倉庫工具介紹 不管是android studio還是xcode,如果沒有遠端程式碼倉庫工具支援,那麼你的專案引用的第三方庫,必須手動下載放到程式碼資料夾一起存放,複雜的話甚至還要額外做一些配置。 用上程式碼倉庫工具,您只需寫上需要依賴庫的名稱就可以,剩下的事情就由工具來幫你去下載相關檔

Navicat for MySQL數據庫管理工具安裝破解

安裝目錄 http 數據庫 官方下載 有一個 .com x64 load 安裝 Navicat for MySQL官方下載地址:https://www.navicat.com/en/download/navicat-for-mysql 1、下載後安裝 navicat110_

做一個合格的前端,gulp自動化構建工具入門教程

安裝完成 基本 合成 node.js 文件替換 mage 9.png basename 加載 我的新作觀點網http://www.guandn.com (觀點網是一個獵獲新奇、收獲知識、重在獨立思考的網站),它前端js、css的壓縮、合並、md5命名等就使用了gulp自動化

Ansible批量自動化管理工具入門

這樣的 ase 更新 系統版本 roo art 啟動服務 移除 nag 一、虛擬機版本 1、需要利用7.5版本虛擬機 2、7.5版註意事項: 【2.1】、網卡名叫ens32同樣配置文件也是ens32 【2.2】、命令:systemctl 統一管理命令, 例,systemct

大資料領域兩大最主流叢集管理工具AmbariCloudera Manger

目前啊,都知道,大資料叢集管理方式分為手工方式(Apache hadoop)和工具方式(Ambari + hdp 和Cloudera Manger + CDH)。    手工部署呢,需配置太多引數,但是,好理解其原理,建議初學這樣做,能學到很多。該方式啊,均得由使用者執

python版本管理工具pyenvpipenv包管理工具 centos6.9

一、pyenv版本管理工具 pyenv是一個python版本管理工具,可以實現輕鬆切換多個python版本 它可根據每個使用者更改全域性python版本,也可以為每個專案指定python版本,還可以管理virtualenv虛擬環境,可以自己建立virtualenv或者通過pyenv-virt

iOS 依賴管理工具 CocoaPods Carthage 的使用及原理

       隨著網際網路的高速發展,個大網際網路公司為更高效研發自己的產品,而不斷研發適合自己的平臺的開發語言。當這些新的語言被廣泛推廣、被更多的開發團隊所接納,被用於開發不同的場景,這個過程中會研發出很多很多方便開發的框架。發展到一定階段,都會出現相應的依賴管理工具。例如

原始碼管理工具SVNGit小結

這篇文章主要是對原始碼管理工具進行了一些總結,也算是自己對相關知識的一個梳理。文章主要從為什麼使用,基本知識,二者之間的一些常用指令的對比以及衝突的解決進行梳理。文章只是自己的一些理解,可能會有一些偏差,有問題的可以隨時提出! 一、為什麼要使用原始碼管理工具 1、能記錄一個

ubuntu下安裝gulpbower前端自動構建工具

ubuntu下安裝gulp和bower前端自動構建工具 1、前提是你在ubuntu下安裝好了 node和npm 教程網上有很多,嘗試了很多遍,趁熱把方法記錄下來 2.如果你之前裝好了,npm和node但是不能用,就先把他們都解除安裝了,然後按照我的方法重新安裝一遍: ubuntu下安

IntelliJ IDEA相關小技巧外掛 | Mybatis自動生成工具

本文簡單介紹一些idea開發常用外掛和工具,以及一些小技巧,不足之處希望大家指出,我改正。不喜勿噴! 一、IDEA開發小技巧 在使用idea開發過程中我們會對介面有一些潔癖(簡稱強迫症),下面簡單介紹一下個人的習慣: 1.idea如何檢視檔案或專案的歷史提交記錄 在

版本管理工具小烏龜TortoiseGit的安裝使用(1)

姓名 save 使用 一行 https 技術 安裝路徑 管理工具 gen 1、軟件的安裝:1.1 安裝 Git使用軟件管理工具搜索 Git: 先安裝 Git(也可以在 https://git-for-windows.github.io/ 找到最新版),全部選擇默認即可;再安

在Windows7上安裝使用AD DS管理工具

微軟公司 windows7 ad ds 域 管理工具 為什麽要安裝AD DS管理工具 要管理活動目錄,默認只有在域控制器下才可以,管理員對活動目錄的管理和維護又比較頻繁,因此需要經常出入機房才能完成管理任務 用遠程桌面也可以進行域管理,但有一定的安全隱患,還會產生較大的網絡流量,占

Mybatis自動生成實體類實體映射工具

ase 忽略 路徑 package mapping decimal rri upd 需要 Mybatis Mysql生成實體類 用到的Lib包: mybatis-generator-core-1.3.2.jarmysql-connector-java-5.1.30.jar

JavaScript自動化構建工具入門----grunt、gulp、webpack

cli 簡單 cpu占用率高 mini tco get %20 pan 情況 蠻荒時代的程序員: 做項目的時候,會有大量的js 大量的css 需要合並壓縮,大量時間需要用到合並壓縮 在前端開發中會出現很多重復性無意義的勞動 自動化時代的程序員: 希望一切都可以自動完

WebApp的自動測試工具: protractorselenium

ttext exp 數組 dex 測試的 action angular tor trac Protractor是Selenium的擴充,支持Angularjs element(by.css(‘my-css‘)).click(); 一、用by的各種Locato

Linux 入門記錄:二十、Linux 包管理工具 YUM

倉庫 清理 bug entos 需要 tro eat 參數 基於組 一、YUM(Yellowdog Updater, Modified) 1. yum 簡介 RPM 軟件包形式管理軟件雖然方便,但是需要手動解決軟件包的依賴問題。很多時候安裝一個軟件首先需要安裝 1 個或

Mac OSX python多版本管理工具:pyenv virtualenv搭建

macos pyenv pyenv-virtualenv本博文只是簡單介紹如何安裝 概念問題 請自行查詢環境:10.13.1+shell1、安裝brew官網地址:https://brew.sh//usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercon

服務器陣列管理工具之percclistorccli

arc 丟失 硬盤模式 pan echo solid 就是 color brush 前言:在工作場景中,不乏遇到在線陣列配置或硬盤模式更改的。為了方便理解,打一個不是很恰當的比方:一臺業務機器除系統盤外全部單盤raid0做數據掛載,在業務運行過程中,有一塊硬盤壞了,我們在線

PHP的依賴管理工具Composer介紹使用

PHP的依賴管理工具Composer介紹官方文檔:http://docs.phpcomposer.com/00-intro.html#System-Requirements linx上安裝:下載 Composer 的可執行文件 局部安裝要真正獲取 Composer,我們需要做兩件事。首先安裝 Composer