做者:Jogis
原文連接:https://github.com/yesvods/Blog/issues/1
轉載請註明原文連接以及做者信息css
提到 Gulp,不得不說到的是較早的 JS 項目自動化構建工具——Grunt。前端
前端開發過程當中,特別是最近幾年多了 CoffeeScript、Sass、Less 等一些預編譯語言,不少代碼每次寫完須要手動到工做目錄去編譯才能執行。此外,項目預發佈時候須要進行 js、css 文件合併、壓縮、重命名等操做,實在是很繁瑣。此前不少工程師使用的是 Makefile 構建項目,可是這要求須要必定Linux基礎,並且編寫配置文件會增大很是多工做量, Grunt 的出現,解放了前端工程師的雙手=_=node
Grunt 經過 CLI 配合配置文件 gruntfile.js 去完成自動化構建任務,社區有很是多的 Grunt 插件,好比 concat(合併文件)、 uglify(js壓縮),只須要在 gruntfile.js 中配置好路徑等一些參數,運行如下命令就能夠自動執行。c++
grunt takeName
Gulp是一款 The streaming build system(流式構建系統),若是說 Grunt 是基於 gruntfile.js 任務執行器,Gulp 就是基於 NodeJS 的文件流任務執行器,比起 Grunt 有以下特色git
使用方便
經過代碼優於配置的策略,Gulp 可讓簡單的任務簡單,複雜的任務更可管理。github
構建快速
經過流式操做,減小頻繁的 IO 操做,更快地構建項目。npm
插件高質
Gulp 有嚴格的插件指導策略,確保插件能簡單高質的工做。gulp
易於學習
少許的API,掌握 Gulp 能夠絕不費力。構建就像流管道同樣,輕鬆加愉快。promise
Gulp 主要 API 爲 gulp.src(使用glob模式匹配得到文件流集)、gulp.dest(輸出gulp文件流集到指定路徑,路徑指定相對於gulpfile.js配置文件)、gulp.watch(監聽glob模式匹配的文件集,有改動時執行相應gulp任務),如圖:瀏覽器
譯做管絃樂演奏家,大多數就是一個老頭拿着個小棍的形象,就像這樣:
一個npmjs模塊,就是一個以最大併發方式去排序或執行一系列的任務。這些任務就是咱們以後會用到的 Gulp 任務,好比說 css 命名的任務,裏面包括css的瀏覽器前綴添加、合併、壓縮等操做。orchestrator 經過實例化一個對象,在對象上調用 add 來添加特定命名的任務、添加任務時候能夠聲明任務依賴,好比:
var Orchestrator = require('orchestrator'); var orchestrator = new Orchestrator(); orchestrator.add('thing1', function(){ // do stuff }); orchestrator.add('thing2', function(){ // do stuff }); orchestrator.add('mytask', ['thing1','thing2'], function() { // Do stuff });
以上代碼,添加了3個 Gulp 任務,mytask 任務依賴於 thing1 和 thing2 ,即必須執行完後面兩個任務,mytask才能執行,經過任務依賴,很容易理清和構建任務時候的執行順序。須要注意的是,在填寫 do stuff 時候,要確保其返回一個 promise 或者是 event stream(最經常使用),好比一個簡單的任務是這樣定義的:
var map = require('map-stream'); orchestrator.add('thing4', function(){ var stream = map(function (args, cb) { cb(null, args); }); // do stream stuff return stream; });
或則是返回一個 promise:
var Q = require('q'); orchestrator.add('thing3', function(){ var deferred = Q.defer(); // do async stuff setTimeout(function () { deferred.resolve(); }, 1); return deferred.promise; });
orchestrator 調用 start 來執行特定名稱的任務,可一次執行多個:
orchestrator.start('one', 'two');
以上兩個是 orchestrator 最經常使用的用於實現 Gulp 的函數,除此以外,還有任務檢測,任務暫停,任務事件監聽,想詳細瞭解可訪問npmjs:https://www.npmjs.org/package/orchestrator
這是 Gulp 採用的一個虛擬文件系統,能夠讀取 glob 模式匹配到的文件並轉成文件流,能夠獲取文件流並轉成文件集。其中 vinyl-fs 使用 vinyl 虛擬文件描述類,來對 glob 匹配到的文件進行描述,所謂的描述,只是簡單的文件名與路徑,以及文件內容,能夠說是一個文件的封裝,能夠看看 vinyl 是如何描述一個或一組文件的:
var File = require('vinyl'); var coffeeFile = new File({ cwd: "/", base: "/test/", path: "/test/file.coffee", contents: new Buffer("test = 123") });
除了 vinyl ,vinyl-fs 還須要依賴 glob-stream 讀寫文件流,如圖:
你們可能有疑問,讀寫文件流,爲何不用 nodejs 內核的 steam 類來讀寫呢,騷安勿燥,Gulp 既然是基於 nodejs 構建,最終天然也是依賴 nodejs 內核實現它的功能的。
只是,stream 類讀取文件流只針對一個文件路徑,glob-stream 就是實現從獲取 glob 模式匹配文件集,到轉換成文件路徑,再到讀取,仍是有一段距離的。如圖:
glob-stream 經過 minimatch 來進行 glob 模式匹配,經過其餘路徑模塊,得到一組文件路徑,而後就是 ordered-read-streams 發光發熱時候啦,對這組文件路徑一個個地讀啊,而後就得到一組文件流啦。
好啦,終於分析完 Gulp 的實現,經過對其中模塊的閱讀,其實 Nodejs 模塊有點像樂高積木,內核給出的就是最基本的積木啦,不過你能夠無限次使用它們,來堆出一個個小的物體,經過小小的物體組合,來組成很是徇麗多姿的樂高做品啦~
固然,也是有一些 c++ 實現的nodejs模塊,主要是用於一些須要高性能運算的地方,不過npmjs.org上介紹到的模塊,大部分的依賴都是基於 nodejs 內核實現滴。