Gulp實戰(zhàn)

原文鏈接:www.talkingcoder.com

什么是gulp

Gulp是可以自動化執(zhí)行任務的工具。在平時開發(fā)的流程里面,一定有一些動作需要手工的重復的去執(zhí)行,比如:

  • 把一個文件拷貝到另外一個位置
  • 把多個 JS 或者 CSS 文件合并成一個文件,以減少網(wǎng)絡請求數(shù)
  • 對JS文件和CSS進行合并壓縮,以減少網(wǎng)絡流量
  • 把Sass或者Less文件編譯成CSS
  • 壓縮圖像文件,以減少網(wǎng)絡流量
  • 創(chuàng)建一個可以實時刷新頁面內容的本地服務器等等。

只要你覺得有些動作是要重復去做的,一般你就可以把這些動作創(chuàng)建成一個gulp任務,然后在指定的條件下,比如文件發(fā)生變化以后,自動去執(zhí)行這些任務。

gulp特點

  • 易于使用 通過代碼優(yōu)于配置的策略,Gulp 讓簡單的任務簡單,復雜的任務可管理。
  • 快速構建 利用 node.js 流的威力,你可以快速構建項目并減少頻繁的 IO 操作。前一級的輸出,直接變成后一級的輸入,使得在操作上非常簡單
  • 高質量的插件 Gulp 嚴格的插件指南確保插件如你期望的那樣簡潔地工作。
  • 易于學習 通過最少的 API,掌握 Gulp 毫不費力,構建工作盡在掌握。

官方文檔解釋

  • Stream 是 nodejs 各種對象實現(xiàn)的抽象接口。

  • 比如標準輸入是一個流,標準輸出也是一個流。

  • 所有的 stream 對象都是 EventEmitter 的實例,可以發(fā)射事件。

  • 流是一種有起點和終點的數(shù)據(jù)傳輸手段。

  • 上一個的輸出,是下一個的輸入

  • 上一個的輸出,是下一個的輸入

  • 上一個的輸出,是下一個的輸入

image.png

gulp中的流

  • gulp正是通過流和代碼優(yōu)于配置的策略來盡量簡化任務編寫的工作。
  • 類似jquery里的鏈式操作,把各個方法串連起來構建完整的任務。
  • 用gulp編寫任務也可看作是用Node.js編寫任務。
  • 當使用流時,gulp不需要生成大量的中間文件,只將最后的輸出寫入磁盤,整個過程因此變得非常快。

安裝node

gulp是基于Nodejs的自動任務運行器
安裝Gulp和相關行件用的都是node的包管理工具npm
所以你需要先在電腦上安裝 node,確定在命令行工具的下面可以使用npm這個命令,這樣就能去安裝Gulp了。

node.js官網(wǎng)

安裝好以后,我們可以打開命令行工具,mac 用戶可以使用終端工具,windows 用戶可以找到cmd命令行工具。

安裝gulp

在項目里使用gulp需要

  • 在全局范圍內去安裝一下gulp的命令行工具
  • 然后在項目里面再去本地安裝gulp

gulp 命令行工具

  • 使用 npm install 去安裝 gulp,注意加上一個 -g 的參數(shù),表示在全局范圍內去安裝.
  • 一般用 npm 安裝的時候用一個 -g 的參數(shù)就表示,這個安裝的東西會作為命令去執(zhí)行。
  • 如果你在mac或linux下遇到了權限問題,在下面這個命令的前面加上 sudo npm install gulp -g 并輸入mac密碼。

npm install -g gulp

安裝完成后可以輸入 gulp --help

如果輸出一些幫助的信息就表示可以gulp命令行成功安裝了

如果安裝不上可以換一下源試試

1. 先創(chuàng)建一個目錄

maclinux 操作系統(tǒng)下執(zhí)行

mkdir learngulp

windows 操作系統(tǒng)下執(zhí)行

md learngulp

2. 使用 命令進入此目錄

cd learngulp

3. 創(chuàng)建項目描述文件 package.json

npm,需要一個叫 package.json 的文件來管理依賴,可以手工去創(chuàng)建這個文件,也可以使用 npm init 這個命令。 輸入

npm init

輸入一些問題答案

name: (zhufeng_automation) learngulp //項目名字,npm init會自動取當前目錄名作為默認名字,這里不需要改,直接確認即可
version: (1.0.0) 1.0.0   //項目版本號,這個大家按自己習慣來定就可以
description: learn gulp //項目說明
entry point: (index.js) index.js // 入門文件 npm start 會執(zhí)行此文件
test command: test.js //測試腳本 npm test 會執(zhí)行此文件
git repository: (https://github/zhufengpeixun/zhufeng_automation.git) //模塊的git倉庫,選填。npm的用戶一般都使用github做為自己的git倉庫
keywords: node.js gulp  //在npmjs官網(wǎng)搜索時的關鍵字
author: zhangrenyang //項目作者名字
license: (ISC) MIT //授權協(xié)議
About to write to D:\mygit\zhufeng_automation\package.json:

{
  "name": "learngulp",
  "version": "1.0.0",
  "description": "learn gulp",
  "main": "index.js",
  "dependencies": {
    "gulp": "^3.9.0"
  },
  "devDependencies": {},
  "scripts": {
    "test": "test.js"
  },
  "repository": {
    "type": "git",
    "url": "https://git.coding.net/zhufengpeixun/zhufeng_automation.git"
  },
  "keywords": [
    "node.js",
    "gulp"
  ],
  "author": "zhangrenyang",
  "license": "MIT"
}

Is this ok? (yes) yes //對以上內容確認無誤后,就可以直接回車確認了

回車后會在當前目錄下創(chuàng)建一個 package.json 文件

這樣可以把 gulp 作為項目的開發(fā)依賴(只在開發(fā)時用,不會發(fā)布到線上),通過

npm install gulp --save-dev

在node_modules下安裝本地的gulp庫并把添加配置到 package.json 文件里面。

"devDependencies": {
    "gulp": "^3.9.0"
  }

1.創(chuàng)建配置文件:

gulp 的任務要放到一個叫 gulpfile.js 的文件里面,先在項目的根目錄下面創(chuàng)建一個這樣的文件。 然后在這個文件的頂部添加下面這行代碼:

   var gulp = require('gulp');

通過require可以把gulp模塊引入當前項目并賦值給gulp變量
這樣,gulp 這個變量里面就會擁有 gulp 的所有的方法了

2.創(chuàng)建gulp的任務

可以使用gulp的task方法
同樣我們去創(chuàng)建一個叫 hello 的任務,它要做的事就是在控制臺上輸出 "您好" 這兩個字
第一個參數(shù)是任務的名稱,第二個參數(shù)是任務的定義,是一個匿名函數(shù)

gulp.task('hello', function () {
  console.log('您好');
});

執(zhí)行 Gulp 的任務,打開命令行工具,進入到項目所在的目錄,然后輸入:

gulp hello

會返回:

$ gulp hello
[21:36:34] Using gulpfile D:\mygit\zhufeng_automation\gulpfile.js
[21:36:34] Starting 'hello'...
您好
[21:36:34] Finished 'hello' after 959 μs

gulp后面跟著的是任務的名稱,不輸入任務名稱的話會默認找default任務,找不到會報錯

執(zhí)行其它任務

可以使用

gulp <task> <othertask>

gulp 只有你需要熟知的參數(shù)標記,其他所有的參數(shù)標記只在一些任務需要的時候使用。

  • -v 或 --version 會顯示全局和項目本地所安裝的 gulp 版本號
  • --gulpfile 手動指定一個 gulpfile 的路徑,這在你有很多個 gulpfile 的時候很有用。這也會將 CWD 設置到該 gulpfile 所在目錄
  • --cwd dirpath 手動指定 CWD。定義 gulpfile 查找的位置,此外,所有的相應的依賴(require)會從這里開始計算相對路徑
  • -T 或 --tasks 會顯示所指定 gulpfile 的 task 依賴樹
  • --tasks-simple 會以純文本的方式顯示所載入的 gulpfile 中的 task 列表
  • --color 強制 gulp 和 gulp 插件顯示顏色,即便沒有顏色支持
  • --no-color 強制不顯示顏色,即便檢測到有顏色支持
  • --silent 禁止所有的 gulp 日志

gulp.js工作方式

gulp的使用流程一般是:首先通過gulp.src()方法獲取到想要處理的文件流,
然后把文件流通過pipe方法導入到gulp的插件中,
最后把經(jīng)過插件處理后的流再通過pipe方法導入到gulp.dest()中,
gulp.dest()方法則把流中的內容寫入到文件中。例如:

var gulp = require('gulp');
 gulp.src('script/src.js')         // 獲取文件的流的api
    .pipe(gulp.dest('dist/dest.js')); // 寫文件的api

使用gulp,僅需知道4個API即可:gulp.task(),gulp.src(),gulp.dest(),gulp.watch(),所以很容易就能掌握

gulp.src()

在Gulp中,使用的是Nodejs中的stream(流),首先獲取到需要的stream,然后可以通過stream的pipe()方法把流導入到你想要的地方,比如Gulp的插件中,經(jīng)過插件處理后的流又可以繼續(xù)導入到其他插件中,當然也可以把流寫入到文件中。所以Gulp是以stream為媒介的,它不需要頻繁的生成臨時文件,這也是Gulp的速度比Grunt快的一個原因。再回到正題上來,gulp.src()方法正是用來獲取流的,但要注意這個流里的內容不是原始的文件流,而是一個虛擬文件對象流(Vinyl files),這個虛擬文件對象中存儲著原始文件的路徑、文件名、內容等信息,這個我們暫時不用去深入理解,你只需簡單的理解可以用這個方法來讀取你需要操作的文件就行了。其語法為:

gulp.src(globs[, options]) 

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

glob語法

gulp內部使用了node-glob模塊來實現(xiàn)其文件匹配功能。我們可以使用下面這些特殊的字符來匹配我們想要的文件:

[圖片上傳失敗...(image-131e3-1531969756686)]

下面以例子來加深理解

glob匹配

image.png

gulp.dest()

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

 gulp.dest(path[,options]) 

path為寫入文件的路徑
options為一個可選的參數(shù)對象,通常我們不需要用到

要想使用好gulp.dest()這個方法,就要理解給它傳入的路徑參數(shù)與最終生成的文件的關系。

gulp的使用流程一般是這樣子的:首先通過gulp.src()方法獲取到我們想要處理的文件流,
然后把文件流通過pipe方法導入到gulp的插件中,最后把經(jīng)過插件處理后的流再通過pipe方法導入到gulp.dest()中,
gulp.dest()方法則把流中的內容寫入到文件中,
這里首先需要弄清楚的一點是,我們給gulp.dest()傳入的路徑參數(shù),只能用來指定要生成的文件的目錄,
而不能指定生成文件的文件名,它生成文件的文件名使用的是導入到它的文件流自身的文件名,
所以生成的文件名是由導入到它的文件流決定的,即使我們給它傳入一個帶有文件名的路徑參數(shù),
然后它也會把這個文件名當做是目錄名,例如:

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

要想改變文件名,可以使用插件 gulp-rename

下面說說生成的文件路徑與我們給gulp.dest()方法傳入的路徑參數(shù)之間的關系。
gulp.dest(path)生成的文件路徑是我們傳入的path參數(shù)后面再加上gulp.src()中有通配符開始出現(xiàn)的那部分路徑。例如:

var gulp = reruire('gulp');

//有通配符開始出現(xiàn)的那部分路徑為 `**/*.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') //沒有通配符出現(xiàn)的情況
.pipe(gulp.dest('dist')); //最后生成的文件路徑為 dist/avalon.js

//有通配符開始出現(xiàn)的那部分路徑為 **/underscore.js
gulp.src('script/**/underscore.js')
//假設匹配到的文件為script/util/underscore.js
.pipe(gulp.dest('dist')); //則最后生成的文件路徑為 dist/util/underscore.js

gulp.src('script/*') //有通配符出現(xiàn)的那部分路徑為 *
//假設匹配到的文件為script/zepto.js    
.pipe(gulp.dest('dist')); //則最后生成的文件路徑為 dist/zepto.js 

通過指定gulp.src()方法配置參數(shù)中的base屬性,我們可以更靈活的來改變gulp.dest()生成的文件路徑。
當我們沒有在gulp.src()方法中配置base屬性時,base的默認值為通配符開始出現(xiàn)之前那部分路徑,例如:

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

上面我們說的gulp.dest()所生成的文件路徑的規(guī)則,其實也可以理解成,用我們給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參數(shù),此時默認的base路徑為script/lib
 //假設匹配到的文件為script/lib/jquery.js
.pipe(gulp.dest('build')) //生成的文件路徑為 build/jquery.js

gulp.src(script/lib/*.js, {base:'script'}) //配置了base參數(shù),此時base路徑為script
//假設匹配到的文件為script/lib/jquery.js
.pipe(gulp.dest('build')) //此時生成的文件路徑為 build/lib/jquery.js     
用gulp.dest()把文件流寫入文件后,文件流仍然可以繼續(xù)使用。

gulp.task()

gulp.task方法用來定義任務,其語法為:

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

name 為任務名
deps 是當前定義的任務需要依賴的其他任務,為一個數(shù)組。當前定義的任務會在所有依賴的任務執(zhí)行完畢后才開始執(zhí)行。如果沒有依賴,則可省略這個參數(shù)
fn 為任務函數(shù),我們把任務要執(zhí)行的代碼都寫在里面。該參數(shù)也是可選的。

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

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

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

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

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

//two任務雖然依賴于one任務,但并不會等到one任務中的異步操作完成后再執(zhí)行

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

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

那如果我們想等待異步任務中的異步操作完成后再執(zhí)行后續(xù)的任務,該怎么做呢?
有三種方法可以實現(xiàn):
第一:在異步操作完成后執(zhí)行一個回調函數(shù)來通知gulp這個異步任務已經(jīng)完成,這個回調函數(shù)就是任務函數(shù)的第一個參數(shù)。

 gulp.task('one',function(cb){ //cb為任務函數(shù)提供的回調,用來通知任務已經(jīng)完成
  //one是一個異步執(zhí)行的任務
  setTimeout(function(){
    console.log('one is done');
    cb();  //執(zhí)行回調,表示這個異步任務已經(jīng)完成
  },5000);
});

//這時two任務會在one任務中的異步操作完成后再執(zhí)行

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){
  var deferred = Q.defer();
  // 做一些異步操作
  setTimeout(function() {
     deferred.resolve();
  }, 5000);
  return deferred.promise;
});

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

gulp.task()就這些了,主要是要知道當依賴是異步任務時的處理。

gulp.watch()

gulp.watch()用來監(jiān)視文件的變化,當文件發(fā)生變化后,我們可以利用它來執(zhí)行相應的任務,例如文件壓縮等。其語法為

gulp.watch(glob[, opts], tasks) 

glob 為要監(jiān)視的文件匹配模式,規(guī)則和用法與gulp.src()方法中的 glob 相同。
opts 為一個可選的配置對象,通常不需要用到
tasks 為文件變化后要執(zhí)行的任務,為一個數(shù)組

gulp.task('uglify',function(){
  //do something
});
gulp.task('reload',function(){
  //do something
});
gulp.watch('js/**/*.js', ['uglify','reload']); 

gulp.watch()還有另外一種使用方式:

gulp.watch(glob[, opts, cb]) 

globopts 參數(shù)與第一種用法相同
cb參數(shù)為一個函數(shù)。每當監(jiān)視的文件發(fā)生變化時,就會調用這個函數(shù),并且會給它傳入一個對象,該對象包含了文件變化的一些信息,type屬性為變化的類型,可以是 added , changed , deletedpath 屬性為發(fā)生變化的文件的路徑

 gulp.watch('js/**/*.js', function(event){
    console.log(event.type); //變化類型 added為新增,deleted為刪除,changed為改變 
    console.log(event.path); //變化的文件的路徑
}); 

1. 導入gulp

打開 gulpfile.js ,在這里先去創(chuàng)建一個對象,叫 gulp ,讓它等于 require('gulp');
這樣這個 gulp 對象就擁有了 gulp 提供的所有屬性還有方法了。

2. 創(chuàng)建源文件

mkdir app
在app下創(chuàng)建 index.html

3. 任務目標

然后用 gulp 的 task 方法,去創(chuàng)建一個任務,
這個任務要做的事就是把我們項目里的app下的index.html 這個文件,復制到一個叫 dist 的目錄里面,這個 dist 目錄表示的是 distribution,也就是正式發(fā)新版。

4. 編寫任務

  1. 先給這個任務起個名字 ... 可以叫它 copy-html
  2. 再寫一個匿名函數(shù)
  3. 先用寫 return
  4. 大部分的 gulp 任務,首先要做的就是去讀取要處理的文件,讀取文件用的是 src 這個方法,在這個方法里,指定一下要讀取的文件 index.html
    找到要處理的文件以后,再用一個 pipe方法,你可以把這個 pipe 想像成是一個管道, 把文件讀取進來,放到一個管道里,在這個管道里面,你可以使用 gulp 的插件去處理讀取進來的文件
    因為這里我們只是簡單的把文件保存到一個指定的地方,所以不需要使用插件,可以使用 gulp 的 dest 這個方法,在這個方法里,指定一下文件要存儲到的那個位置。
    這樣我們就創(chuàng)建好了這個把單個文件復制到指定位置的任務

5. 執(zhí)行

打開命令行工具
先確定當前的位置是在項目的目錄里面
然后輸入 gulp+后面加上任務的名字

gulp copy-html

輸入回車,會出現(xiàn)一些提示:

  • 使用的 gulpfile 的位置
  • 開始執(zhí)行的任務
  • 還有任務結束所花的時間

代碼

 var gulp = require('gulp');
 gulp.task('copy-html',function(){
     return gulp.src('app/index.html').pipe(gulp.dest('dist'));
 });

1. 導入gulp

打開 gulpfile.js ,在這里先去創(chuàng)建一個對象,叫 gulp ,讓它等于 require('gulp');
這樣這個 gulp 對象就擁有了 gulp 提供的所有屬性和方法了。

2. 創(chuàng)建源文件

在app下創(chuàng)建
[圖片上傳失敗...(image-b235d5-1531969756685)]

3. 任務目標

然后用gulp的task方法,去創(chuàng)建一個任務,
把imgs目錄里的文件復制到dist這個目錄的下面

4. 編寫任務

  1. 先給這個任務起個名字 ... 可以叫它 copy-imgs
  2. 再寫一個匿名函數(shù)
  3. 先寫 return
  4. 大部分的 gulp 任務,首先要做的就是去讀取要處理的文件,讀取文件用的是 src 這個方法
    'app/imgs/*.png' 指app/imgs/這個目錄里面的所有的.png格式的圖片,這個 * 號表示的就是任何東西. *.png 意思就是,不管圖片的文件名是什么,只要它是 .png 格式的就行.
gulp.src('app/imgs/*.png')

5. 執(zhí)行

打開命令行工具
先確定當前的位置是在項目的目錄里面
然后輸入 gulp+后面加上任務的名字

gulp copy-imgs

輸入回車,會出現(xiàn)一些提示:

  • 使用的 gulpfile 的位置
  • 開始執(zhí)行的任務
  • 還有任務結束所花的時間

完成以后,你會看到,在項目的dist這個目錄里面,會創(chuàng)建一個叫imgs的目錄,在這個目錄里面,有兩張圖片1.png 2.png它們都是從項目根目錄下的imgs這個目錄里面復制過來的.
在這個目錄里面,這張jpg格式的圖片,還有small里面的圖片,并沒有復制到dist下面的 imgs 目錄里面。因為我們寫的glob只匹配imgs目錄下的所有的.png格式的圖片

6.指定多個后綴

如果你想把 imgs 目錄下面的所有的圖像文件都復制到 dist 下面的 imgs 目錄里面,在這個 src 方法的 glob 里面,可以指定多個擴展名,現(xiàn)在是 *.png, 后面加上一組花括號,在這個花括號里面,指定多個擴展名.{jpg,png}注意逗號的后面不要使用空格.

多個glob

有些任務你可能需要用到多個glob,這樣我們就可以用一個數(shù)組,數(shù)組里的每個項目表示的就是用來匹配文件的glob。
比如我們的項目里有兩個目錄,css還有js。
每個目錄下面都有一些文件。
我們想創(chuàng)建一個任務,需要用到這兩個目錄里面的東西。
在這個任務里,我們就可以使用多個glob。

    ['app/css/*.css','app/js/*.js']

數(shù)組里有兩個glob
再次執(zhí)行任務
會發(fā)現(xiàn)glob中的文件都拷貝到dist下面去了

排除特定文件

glob 的前面,再加上一個!號,表示這是要排除掉的文件

['app/css/*.css','app/js/*.js','!app/js/*.tmp.js']

代碼

var gulp = require('gulp');

/**
 * 復制圖片
 */
gulp.task('copy-images',function(){
    return gulp.src('app/imgs/*.jpg').pipe(gulp.dest('dist'));
});

/**
 * 1\. {} 里可以指定多個擴展名
 * 2\. * 匹配所有的字符,除了路徑分隔符 /
 * 3\. ** 匹配所有的字符,包括路徑分隔符 /
 */
gulp.task('copy-images',function(){
    return gulp.src('app/imgs/**/*.{jpg,png}').pipe(gulp.dest('dist'));
});

/**
 * 匹配多個目錄 glob
 * 可以填寫一個數(shù)組
 *
 */
gulp.task('copy-other',function(){
    return gulp.src(['app/css/*.css','app/js/*.js'],{base:'app'}).pipe(gulp.dest('dist'));
});

/**
 * 匹配多個目錄 glob
 * ! 排除一個文件
 *
 */
gulp.task('copy-other',function(){
    return gulp.src(['app/css/*.css','app/js/*.js','!app/js/*.tmp.js'],{base:'app'}).pipe(gulp.dest('dist'));
});

1. 組合任務

在創(chuàng)建 gulp 任務的時候,我們可以去給任務指定它依賴的其它的任務。
比如,這里我們創(chuàng)建了三個任務,copy-html,copy-imgs,copy-other。
我們想再創(chuàng)建一個叫 build 的任務,這個任務依賴這里的這三個任務。

2. 編寫

使用gulp的task這個方法去創(chuàng)建任務
先給這個任務起個名字,叫做 build.
再把這個方法的第二個參數(shù)設置成一個數(shù)組,這個數(shù)組里的項目就是這個任務所依賴的任務,輸入一組方括號,再把它需要的三個任務,作為這個數(shù)組的三個項目.
我們可以繼續(xù)去設計這個任務要作的事情,用一個匿名函數(shù),
可以讓它在控制臺上輸出 編譯成功 ,這樣在執(zhí)行 build 任務的時候,會先去執(zhí)行它依賴的三個任務,最后再執(zhí)行它本身要做的任務。

3. 執(zhí)行

保存,打開命令行工具,輸入 gulp build,回車.
注意這里會同時去執(zhí)行 build 需要的三個任務,并不是先執(zhí)行一個,等待完成以后再去執(zhí)行一個,
這些依賴的任務是同時執(zhí)行的,等它們都完成以后,才會執(zhí)行 build 本身要做的任務,這里就是在控制臺上,輸出編譯成功 這幾個字兒。

代碼

var gulp = require('gulp');

gulp.task('copy-html',function(){
    return gulp.src('app/index.html').pipe(gulp.dest('dist'));
});

gulp.task('copy-images',function(){
    return gulp.src('app/imgs/**/*.{jpg,png}').pipe(gulp.dest('dist'));
});

/**
 * 匹配多個目錄 glob
 * ! 排除一個文件
 *
 */
gulp.task('copy-other',function(){
    return gulp.src(['app/css/*.css','app/js/*.js','app/js/*.tmp.js'],{base:'app'}).pipe(gulp.dest('dist'));
});

gulp.task('default',['copy-html','copy-images','copy-other'],function(){
    console.log('全部拷貝任務執(zhí)行完畢!');
});

1. 監(jiān)聽任務

使用 gulp 的 watch 這個方法,我們可以去監(jiān)視一些文件,當這些文件發(fā)生變化的時候,立即去執(zhí)行一些指定的任務

2.編寫

先打開 gulpfile.js,再去創(chuàng)建一個任務
gulp.task,這個任務可以叫做 watch,再用一個匿名函數(shù),在它里面,再用 gulp 的 watch 方法去做點事情。

輸入 gulp.watch(),先指定一下要監(jiān)視的文件,比如去監(jiān)視 index.html
再把要執(zhí)行的任務列表放到這里,這個任務列表要放到一個數(shù)組里,所以先輸入一組方括號,要執(zhí)行的任務是 copy-html.
它的意思就是,我們在執(zhí)行 watch 任務的時候,去監(jiān)視 index.html 這個文件的變化,當這個文件發(fā)生變化以后,就去自動執(zhí)行 copy-html 這個任務。

執(zhí)行

保存 回到命令行工具
先去執(zhí)行一下剛才創(chuàng)建的 watch 這個任務 gulp watch ,這樣 gulp 就會去監(jiān)視文件的變化了,你會看到這個任務并沒有立即結束,它會一直運行,直到我們手工退出這個任務,退出可以按一上 ctrl + C
再回到項目,打開 index.html 這個文件,隨便修改一個地方,然后保存一下,回到命令行,你會看到 gulp 執(zhí)行了 copy-html 這個任務,因為 index.html 這個文件發(fā)生了變化

每次保存被監(jiān)視的文件,都會去執(zhí)行指定的任務列表。
回到項目,打開 dist 下面的 index.html,你會看到修改之后的 index.html 已經(jīng)被復制到了這個目錄的下面.

代碼

var gulp = require('gulp');

gulp.task('copy-html',function(){
    return gulp.src('app/index.html').pipe(gulp.dest('dist'));
});

gulp.task('copy-images',function(){
    return gulp.src('app/imgs/**/*.{jpg,png}',{base:'app'}).pipe(gulp.dest('dist'));
});

/**
 * 匹配多個目錄 glob
 * ! 排除一個文件
 *
 */
gulp.task('copy-other',function(){
    return gulp.src(['app/css/*.css','app/js/*.js','app/js/*.tmp.js'],{base:'app'}).pipe(gulp.dest('dist'));
});

//在執(zhí)行watch的時候會監(jiān)控index.html文件的變化,發(fā)生變化后可以執(zhí)行拷貝html的任務
gulp.task('default',function(){
    gulp.watch('app/index.html',['copy-html']);
    gulp.watch('app/imgs/**/*.{jpg,png}',['copy-images']);
    gulp.watch(['app/css/*.css','app/js/*.js','app/js/*.tmp.js'],['copy-other']);
});

gulp插件


gulp提供了一些很實用的接口,但本身并不能做太多的事情。
可以讀取文件、寫入文件以及監(jiān)控文件等一少部分功能。
其它實用的功能都是依靠插件來進行擴展的。
這些插件可以實現(xiàn)比如

  • 編譯 Sass:gulp-sass
  • 編譯 Less:gulp-less
  • 合并文件:gulp-concat
  • 壓縮js 文件:gulp-uglify
  • 重命名js文件:gulp-rename
  • 優(yōu)化圖像大小:gulp-imagemin
  • 壓縮css 文件:gulp-minify-css
  • 創(chuàng)建本地服務器:gulp-connect
  • 實時預覽 gulp-connect

插件列表

使用插件

1.  npm install xxx --save-dev 安裝插件
2.  在 **gulpfile.js** 頂部引入此插件
3.  在創(chuàng)建任務的時候使用此插件

自動加載gulp 插件

gulp-load-plugins這個插件能自動幫你加載package.json文件里的gulp插件。
例如假設你的package.json文件里的依賴是這樣的:

"devDependencies": {
   "gulp": "^3.9.0",
   "gulp-concat": "^2.6.0",
   "gulp-connect": "^2.2.0",
   "gulp-imagemin": "^2.3.0",
 }

然后我們可以在gulpfile.js中使用gulp-load-plugins來幫我們加載插件:

var gulp = require('gulp');
//加載gulp-load-plugins插件,并馬上運行它
var $ = require('gulp-load-plugins')();

然后我們要使用gulp-rename和gulp-ruby-sass這兩個插件的時候,
就可以使用.concat和.connect來代替了,也就是原始插件名去掉gulp-前綴,之后再轉換為駝峰命名。

less

less插件可以把less文件編譯成css

less任務

可以在app/less下面創(chuàng)建文件page.less,然后就可以把此文件編譯到dist下面

安裝插件

    npm install gulp-less --save-dev

安裝后可以在node-modules里看到此插件
也可以在package.json的devDependencies里面看到此插件的配置

代碼如下

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

gulp.task('less',function(){
    return gulp.src('app/less/*.less').pipe(less()).pipe(gulp.dest('dist/css'));
});

gulp.task('default',['less']);

sass

想要使用 Gulp 去把 Sass 編譯成 CSS ,我們可以使用 gulp-sass 這個插件。

插件任務

可以在app/sass下面創(chuàng)建文件base.scss,然后就可以把此文件編譯到dist下面

安裝插件

npm install gulp-sass --save-dev

安裝后可以在node-modules里看到此插件

也可以在package.json的devDependencies里面看到此插件的配置 "gulp-sass": "^2.0.4"

使用插件

在項目里面,app/sass 這個目錄的下面,有一個sass文件,就是這個base.scss

$blue : #1875e7; 
  div {
   color : $blue;
  }

下面,我們可以使用gulp-sass這個插件,把這個目錄里面的sass文件編譯成css ,
再放到 dist 目錄下面的 css 這個目錄的下面。

代碼如下

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

gulp.task('sass',function(){
    return gulp.src('app/sass/*.scss').pipe(sass()).pipe(gulp.dest('dist/css'));
});

gulp.task('default',['sass']);

gulp-connect

有些時候我們需要把文件放到本地服務器上去預覽,gulp-connect可以幫我們創(chuàng)建一個本地服務器去運行我們的項目

安裝插件

     npm install gulp-connect --save-dev

加上一個 --save-dev,把這個插件放到開發(fā)依賴里面。

創(chuàng)建任務

打開 gulpfile.js
先在文件的頂部這里
去包含一下這個 gulp-connect 插件
給它起個名字connect ...
var connect = require('gulp-connect');

代碼如下

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

    gulp.task('server',function(){
       connect.server({
           root:'dist',//服務器的根目錄
           port:8080 //服務器的地址,沒有此配置項默認也是 8080
       });
    });

    gulp.task('default',['server']); //運行此任務的時候會在8080上啟動服務器,

gulp-connect

我們希望當文件變化的時候瀏覽器可以自動刷新,這樣我們就不需要文件修改后手動去刷新瀏覽器了

代碼如下

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

gulp.task('copy-html',function(){
     gulp.src('app/index.html')//指定源文件
         .pipe(gulp.dest('dist'))//拷貝到dist目錄
         .pipe(connect.reload());//通知瀏覽器重啟
});

gulp.task('watch',function(){
    gulp.watch('app/index.html',['copy-html']);//當index.html文件變化時執(zhí)行copy-html任務
});

gulp.task('server',function(){
    connect.server({
        root:'dist',//服務器的根目錄
        port:8080, //服務器的地址,沒有此配置項默認也是 8080
        livereload:true//啟用實時刷新的功能
    });
});
gulp.task('default',['server','watch']);//運行此任務的時候會在8080上啟動服務器,

gulp-concat

這個插件可以把幾個文件合并到一塊

安裝

npm install gulp-concat --save-dev  

代碼如下

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

gulp.task('concat',function(){
    return gulp.src(['app/js/*.js','!app/js/*.tmp.js'])//指定要合并的文件glob
        .pipe(concat('app.js'))//進行合并并指定合并后的文件名
        .pipe(gulp.dest('dist/js'));//輸出到目標路徑
});

gulp.task('default',['concat']);

gulp-concat

合并后我們可以對JS文件進行合并,最小化處理

安裝

先打開命令行安裝

    npm install gulp-uglify --save-dev

代碼如下

var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify')

gulp.task('uglify',function(){
    return gulp.src(['app/js/*.js','!app/js/*.tmp.js'])
        .pipe(concat('app.js')) //把多個JS文件合并成一個文件
        .pipe(uglify()) //對合并后的app.js文件進行壓縮
        .pipe(gulp.dest('dist/js')); //輸出到目的地
});

gulp.task('default',['uglify']);

html文件壓縮

gulp-minify-html插件用來壓縮html文件。

代碼如下

var gulp = require('gulp'),
    minifyHtml = require("gulp-minify-html");

gulp.task('minify-html', function () {
    gulp.src('src/*.html') // 要壓縮的html文件
    .pipe(minifyHtml())    //壓縮
    .pipe(gulp.dest('dist/html'));//輸出到目的地
});

gulp-rename

在把處理好的文件存放到指定的位置之前,我們可以先去重新命名一下它。可以使用gulp-rename這個插件.

安裝

    npm install gulp-rename --save-dev

代碼如下

var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
gulp.task('uglify',function(){
    return gulp.src(['app/js/*.js','!app/js/*.tmp.js'])//指定要處理的文件
        .pipe(concat('app.js'))//合并成一個文件
        .pipe(gulp.dest('dist/js'))//保存此文件
        .pipe(uglify())//進行壓縮
        .pipe(rename('app.min.js'))//對此文件進行重命名
        .pipe(gulp.dest('dist/js'));//再輸出一次
});

gulp.task('default',['uglify']);

gulp-minify-css

如果要想壓縮css,我們可以使用gulp-minify-css

安裝

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

代碼如下

var gulp = require('gulp');
var less = require('gulp-less');
var minify = require('gulp-minify-css');//在文件的頂部去包含這個插件,起個名字,叫做 minify
var rename = require('gulp-rename');
gulp.task('minify',function(){
    return gulp.src('app/less/page.less')//指定 less文件
        .pipe(less())//把less編譯成css
        .pipe(gulp.dest('dist/css'))//輸出到目的地
        .pipe(minify())//對 css再進行壓縮
        .pipe(rename('page.min.css'))//重命名
        .pipe(gulp.dest('dist/css'));//輸出到目的地
});

gulp.task('default',['less']);

gulp-imagemin

如果要想在保證不改變圖像質量的情況下,讓圖像文件的體積變得更小一點,我們可以使用gulp-imagemin

安裝

    npm install gulp-imagemin --save-dev  

代碼如下

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

gulp.task('copy-images',function(){
    return gulp.src('app/imgs/**/*.{jpg,png}')//指定要壓縮的圖片
        .pipe(imagemin()) //進行圖片壓縮
        .pipe(gulp.dest('dist'));//輸出目的地
});

gulp.task('default',['copy-images']);

jshint

可以用此插件進行代碼檢查

安裝

npm install gulp-jshint --save-dev

代碼

    var gulp = require('gulp'),
        jshint = require("gulp-jshint");

    gulp.task('jsLint', function () {
        gulp.src('src/*.js')
        .pipe(jshint()) //進行代碼檢查
        .pipe(jshint.reporter()); // 輸出檢查結果
    });

DEMO :

{
  "name": "tongbanke",
  "version": "1.0.0",
  "description": "tobanke'",
  "main": "main.js",
  "scripts": {
    "test": "test"
  },
  "repository": {
    "type": "git",
    "url": "gulp"
  },
  "keywords": [
    "gulp",
    "test"
  ],
  "author": "kongzhi",
  "license": "ISC",
  "devDependencies": {
    "gulp": "^3.6.2",
    "gulp-coffee": "^1.4.2",
    "gulp-concat": "^2.6.0",
    "gulp-connect": "^2.3.1",
    "gulp-jshint": "^2.0.4",
    "gulp-less": "^3.1.0",
    "gulp-obfuscate": "^0.2.9",
    "gulp-uglify": "^2.0.0",
    "gulp-watch": "^0.6.2",
    "jshint": "^2.9.3"
  }
}

image.png
var gulp = require('gulp');
var concat = require('gulp-concat'); //文件合并
var uglify = require('gulp-uglify'); //文件壓縮
var rename = require('gulp-rename'); //文件重命名
var obfuscate = require('gulp-obfuscate'); //代碼混淆
var connect = require('gulp-connect');  //創(chuàng)建一個本地服務器
jshint = require("gulp-jshint");   //語法校驗
// 語法檢查

gulp.task('jshint', function() {
    console.log('語法檢查...');
    return gulp.src('src/*.js')
        .pipe(jshint())    //進行代碼檢查
        .pipe(jshint.reporter('default')); // 輸出檢查結果
});
//創(chuàng)建一個本地服務器
gulp.task('server',function(){
    console.log("創(chuàng)建本地服務器!")
       connect.server({
           livereload:true,//啟用實時刷新的功能
           root:'./',//服務器的根目錄
           port:12306 //服務器的地址,沒有此配置項默認也是 8080
       });
    });
// 合并文件之后壓縮代碼
gulp.task('minify', function() {
    console.log('壓縮合并');
    return gulp.src('src/*.js')  //指定要合并的文件glob
        .pipe(concat('main.js'))  //進行合并并指定合并后的文件名
        .pipe(gulp.dest('min.js'))  //輸出到目標路徑
        .pipe(uglify())
        .pipe(rename('main.min.js'))
        .pipe(connect.reload())  //通知瀏覽器重啟
        .pipe(gulp.dest('min.js'));

});

// 監(jiān)視文件的變化
gulp.task('watch', function() {
    console.log('文件有變動');
    gulp.watch('src/*.js', ['minify','jshint'],function(event){
         console.log(event.type); //變化類型 added為新增,deleted為刪除,changed為改變 
         console.log(event.path); //變化的文件的路徑
    });
});

// 注冊默認任務
gulp.task('default', ['minify', 'watch','server', 'jshint'], function() {
    console.log('壓縮合并混淆重命名');
    return gulp.src('main.min.js')
        .pipe(obfuscate()); //壓縮完代碼混淆
});
image.png

image.png

轉自: https://juejin.im/entry/586a417561ff4b006d77fe85

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容