gulp --- 前端自動化構建工具

gulp是前端開發過程當中對代碼進行構建的工具,是自動化項目的構建利器;她不只能對網站資源進行優化,並且在開發過程當中不少重複的任務可以使用正確的工具自動完成;使用她,咱們不只能夠很愉快的編寫代碼,並且大大提升咱們的工做效率。css

gulp是基於Nodejs的自動任務運行器, 她能自動化地完成 javascript/coffee/sass/less/html/image/css 等文件的的測試、檢查、合併、壓縮、格式化、瀏覽器自動刷新、部署文件生成,並監聽文件在改動後重復指定的這些步驟。在實現上,她借鑑了Unix操做系統的管道(pipe)思想,前一級的輸出,直接變成後一級的輸入,使得在操做上很是簡單。經過本文,咱們將學習如何使用Gulp來改變開發流程,從而使開發更加快速高效。html

1. gulp使用步驟

1.1 安裝Node.js

參考文章 http://www.cnblogs.com/roddy/p/6524252.html前端

1.2 全局安裝gulp

$ npm install gulp -gjava

查看是否正確安裝。node

$ gulp -vgit

出現版本號表示安裝成功。github

1.3 安裝項目依賴包gulp

咱們新建一個項目文件夾"gulp",而後定位到"gulp"文件中npm

$ cd gulpjson

1.3.1 瞭解package.json

在安裝項目依賴包gulp以前,咱們先來看看package.json文件。
package.json是每一個基於Nodejs項目必不可少的配置文件,其中包括項目名稱、版本號和所須要的依賴包列表等信息,它是存放在項目根目錄中的json文件。

想像一下,若是把項目比做是餐廳中一道菜的話,項目中使用到的依賴包就是這道菜的食材,而package.json文件就是這道菜的食材列表,那麼package.json存在的做用是什麼?我想最主要的做用就是方便管理項目,用過github童鞋都知道,多人協同工做的時候常常會使用pull和push,因爲package.json存在,咱們就不須要對項目依賴歸入版本管理,只須要管理package.json就好了,而後根據package.json本地構建項目依賴。

基於命令行建立package.json文件

$ npm init

而後根據提示輸入。

package.json基本格式(注意:實際json文件中是不容許出現註釋的!)

{
  "name": "gulp",                                       //項目名稱(必須)
  "version": "1.0.0",                                   //項目版本(必須)
  "description": "This is gulp project !",              //項目描述(必須)
  "homepage": "",                                       //項目主頁
  "repository": {                                       //項目資源庫
    "type": "git",
    "url": ""
  },
  "author": {                                           //項目做者信息
    "name": "roddy",
    "email": "xxxxx@.com"
  },
  "license": "ISC",                                     //項目許可協議
  "devDependencies": {                                  //項目依賴列表
    "gulp": "^3.8.11"
  }
}

固然,你也能夠直接在項目根目錄中建立package.json文件,而後複製上面配置代碼進去。OK! 如今"gulp"項目中只有一個"package.json"文件,那麼咱們要怎麼安裝項目依賴包gulp呢?其實咱們"package.json"中"devDependencies"字段已經列出了"gulp"包,咱們只須要根據"package.json"來安裝依賴就能夠了,或者用npm來安裝依賴。

1.3.2 根據package.json安裝gulp依賴

$ npm install

1.3.3 npm安裝gulp依賴

$ npm install gulp --save-dev

細心的你會發現,咱們前面已經全局安裝過了gulp,這裏爲何還要項目安裝一次gulp?全局安裝gulp是讓咱們能使用gulp命令行,項目安裝gulp是讓項目能引用gulp模塊!

1.3.3 建立gulpfile.js

gulpfile.js爲gulp項目的配置文件也是咱們的任務文件,咱們使用gulp對文件進行壓縮、打包這些任務就是寫在gulpfile.js文件中。

咱們在"gulp"項目根目錄中建立一個js文件"gulp.js",代碼以下:

// 引入依賴gulp
var gulp = require( 'gulp' );

// 建立一個'default'任務
gulp.task( 'default', function() {
  // 將你的默認的任務代碼放在這
} );

1.3.4 運行任務

用全局gulp來運行gulpfile.js中的任務(全局安裝gulp才能使用gulp命令,若是沒有全局安裝,這裏會報錯!)

$ gulp

或者執行指定的任務。

$ gulp <taskname>

默認的名爲"default"的任務(task)將會被運行,在這裏,這個任務並未作任何事情。

2. gulp API

好了,瞭解gulp大體的工做步驟後,有必要咱們來學習下gulp中的API,這樣你才能根據本身需求寫gulpfile.js。

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

建立一個gulp任務

name : [String] 任務名稱,中間不要有空格。
deps : [Array] 一個包含任務列表的數組,這些任務會在你當前任務運行以前完成。
fn : [Function] 任務的回調函數,任務具體代碼。

gulp.task( "taskname", [ "task1", "task2", ... ], function() {
    // 將你的任務代碼放在這
} );

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

監視文件,而且能夠在文件發生改動時候作一些事情。它總會返回一個EventEmitter來發射(emit)事件

glob : [String/Array] 監視的文件路徑或者文件路徑數組。
opts : [Object] 傳給依賴包gaze的參數。
tasks : [Array] 須要在文件變更後執行的一個或者多個經過 gulp.task() 建立的 task 的名字。

gulp.task( "task1", function() { console.log( "gulp" ) } );
gulp.task( "default", function() { 
    gulp.watch( "xx.js", [ "task1" ] );
} );

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

監視文件,而且能夠在文件發生改動時候作一些事情。它總會返回一個EventEmitter來發射(emit)事件

glob : [String|Array] 監視的文件路徑或者文件路徑數組。
opts : [Object] 傳給依賴包gaze的參數。
cb : [Function] 每次變更須要執行的回調函數,該函數被傳入一個事件對象event。
├─event.type : [String] 變更類型,"added"、"changed"、"deleted"。
└─event.path : [String] 觸發該事件的文件路徑。

gulp.task( "default", function() {
    gulp.watch( "xx.js", function( event ) {
        console.log( event.path + "is" + event.type );
    } );
}

2.4 gulp.src( globs[, options] )

匹配要處理的源文件路徑,而且返回一個stream它能夠被piped到別的插件中

globs : [String|Array] 匹配glob模式的文件路徑或者文件路徑數組。
├─* : 匹配任意文件名。 例:src/*.js <=> src中全部js文件
├─** : 匹配0個或多個文件夾。 例:src/**/*.js <=> src中0個或多個文件夾中的js文件
├─{} : 匹配多個屬性。 例:src/*.{js,css,html} <=> src中全部js,css,html文件
└─! : 排除文件。 例:!src/a.js <=> 不包含src中的a文件
options : [Object] 三個可選配置
├─options.buffer : [Boolean] 默認 true,設置爲false,將返回file.content的流而且不緩衝文件,處理大文件時很是有用。
├─options.read : [Boolean] 默認 true,設置false,將不執行讀取文件操做,返回null。
└─options.base : [String] 默認 glob通配符以前的路徑,最後替換掉base來獲得輸出文件路徑。

假如咱們src目錄中有一個文件夾js,其中有一個test.js文件

gulp.task( "default", function() {
    // 匹配文件"src/js/test.js", 而且把options.base解析爲"src/js"
    gulp.src( "src/js/*.js" )
    // 用"dist"替換掉base路徑,並寫入該文件"dist/test.js"
    .pipe( gulp.dest( "dist" ) );
} );

gulp.task( "task1", function() {
    // 匹配文件"src/js/test.js", 而且把options.base設置爲"src"
    gulp.src( "src/js/*.js", { base : "src" } )
    // 用"dist"替換掉base路徑,並寫入該文件"dist/js/test.js"
    .pipe( gulp.dest( "dist" ) );
} );

2.5 gulp.dest( path[, options] )

能被 pipe 進來,而且將會寫文件。而且從新輸出(emits)全部數據,所以你能夠將它 pipe 到多個文件夾。若是某文件夾不存在,將會自動建立它

path : [String|Function] 文件將被寫入的路徑(輸出目錄)。也能夠傳入一個函數,在函數中返回相應路徑。
options : [Object] 兩個可選配置。
├─options.cwd : [String] 默認 "options.cwd()",輸出目錄的 cwd 參數,只在所給的輸出目錄是相對路徑時候有效。
└─options.mode : [String] 默認 "0777",八進制權限字符,用以定義全部在輸出目錄中所建立的目錄的權限。

3. 基於gulp的插件

前面介紹了"gulp"怎麼安裝使用以及"gulp"的API,可是"gulp"究竟是怎麼樣對文件進行壓縮、合併等操做的呢?其實"gulp"要完成這些操做,靠的就是基於它的一些功能插件,利用這些插件來對文件進行操做,下面咱們就介紹幾種經常使用的插件。

3.1 CSS文件壓縮

插件 : gulp-clean-css

Github : https://github.com/jakubpawlowicz/clean-css

3.1.1 本地安裝

$ npm install gulp-clean-css --save-dev

3.1.2 使用

建立gulpfile.js

var gulp = require( 'gulp' );
var cleanCss = require( 'gulp-clean-css' );

gulp.task( "default", function() {
    // 讀取"src"中的全部css文件
    return gulp.src( "src/*.css" )
    // 壓縮css文件
    .pipe( cleanCss() )
    // 寫入"dist"文件夾中
    .pipe( gulp.dest( "dist" ) );
} );

運行gulpfile.js中的任務

$ gulp

3.2 靜態資源增長版本號更新文件引用

插件 : gulp-rev、gulp-rev-collector

Github : https://github.com/sindresorhus/gulp-rev
Github : https://github.com/shonny-ua/gulp-rev-collector

首先靜態資源增長版本號發佈這些牽扯到前端工程化問題,之於前端工程化,我這裏不想過多解釋,這裏有篇講解前端工程化的文章連接:https://www.zhihu.com/question/20790576
基本原理就是當靜態資源發生版本更新後,用戶瀏覽器會主動放棄緩存中的靜態資源,從服務器拉取最新資源加載,而那些沒有更新的靜態資源文件則使用瀏覽器緩存,這樣的好處就是既能提升用戶訪問網站的速度提高用戶體驗,還能減輕網站服務器壓力。

要想達到這樣的目的有兩種思路:

非覆蓋式發佈:根據靜態資源內容生成hash值,而後與文件名拼接生成新的靜態資源文件,最後更新頁面中靜態資源引用路徑。

這種方法須要注意的是,先上更新後的靜態資源,再上頁面文件。若是先上頁面文件,頁面中引用的靜態資源路徑是添加版本號的靜態資源,因爲服務器中不存在該版本號的靜態資源,這個時候舊版頁面加載不存在的靜態資源就會致使頁面佈局錯亂甚至報錯。

這種方法的缺點也很是明顯,每更新就會生成一次帶版本號的靜態資源文件,這樣冗餘的靜態資源過多,因此須要本身定時清理掉老版本的靜態資源。目前大公司通常都是使用這一種方法對靜態資源進行版本迭代。

覆蓋式發佈:根據文件內容生成hash值,而後對引用該靜態資源文件的模板連接增長版本參數。

這種方法不論是先上頁面仍是靜態資源,都會致使用戶訪問頁面的時候出現問題,若是先上頁面,新版頁面加載舊版靜態資源,致使頁面佈局錯亂;若是先上靜態資源,那些有舊版靜態資源文件緩存的用戶不會收到影響,可是新用戶訪問舊版頁面加載的是新版靜態資源,這樣仍是會致使頁面佈局錯亂等問題,因此若是必定要使用這種方法,那麼最好是在頁面訪問量少的時間段先上靜態資源文件,再上頁面,固然這種方法比第一種方法的好處就是不會生成冗餘的靜態資源。

var gulp = require( 'gulp' );
var rev = require( 'gulp-rev' );
var revCollector = require( 'gulp-rev-collector' );

gulp.task( "default", function() {
    return gulp.src( "src/*.js" )
    // 生成帶hash版本號文件
    .pipe( rev() )
    // 保存新文件
    .pipe( gulp.dest( "dist" ) )
    // 生成新舊文件名對應的json文件
    .pipe( rev.manifest() )
    // 保存json文件
    .pipe( gulp.dest( "dist" ) );
} );

參考資料:

http://www.ydcss.com/archives/424 http://www.gulpjs.com.cn/docs/getting-started/

相關文章
相關標籤/搜索