近期學習Gulp和Browserify,按照網上的教程能夠實現二者的整合,可是總存在各類疑惑,例如,二者爲何能夠整合、爲何須要一些另外的模塊的輔助才能整合、以及對於NodeJS的Stream API自己的疑惑。只有弄清楚其中的原理,才能本身靈活地運用Gulp來整合一些有用的工具,也能享受Stream API的靈活性。node
NodeJS提供了Stream API來實現基於流的IO。要注意的是,NodeJS提供的Stream API只是一套API,咱們實際使用的是實現了這套API的模塊,例如Socket,或者根據本身的須要實現本身的處理流的模模塊。Stream最靈活的使用方式,應該就是pipe了,pipe能夠將多個流拼接起來,組成一個流水線(pipeline),數據從pipeline的寫入端流入,在組成pipeline的stream中以此對數據進行處理,最後從pipeline的讀取端流出。webpack
NodeJS的流主要有:Readable Stream, Writable Stream, Duplex Stream, Transform Stream 幾種子類型。顧名思義,這四種流的特性以下:git
NodeJS的流有兩種模式(Mode),其實就是根據流中傳遞(讀取,寫入)的數據的類型來區分,分別是:github
通常狀況下流須要在建立的時候指定其模式,一旦建立,則再也不修改其模式,可是能夠經過拼接轉換流來進行模式轉換,並獲得一個新的流,下面會講到。web
NodeJS的Stream API規定:gulp
NodeJS的Readable Stream API提供了pipe方法用於流的拼接,pipe方法接受一個輸出流(Writable Stream)對象做爲參數,同時返回該輸出流的引用,若是,該做爲參數的輸出流是一個Duplex Stream,也即返回值同時也是一個Readable Stream,則能夠用這種方式拼接:streamA.pipe(streamB).pipe(streamC)....
拼接的起點,即第一個流,能夠是隻讀流(即不可寫的Readable Stream);拼接的終點,即最後一個流,能夠是純輸出流(即不可讀的Writable Stream);位於中間的流必須是Duplex Stream。api
不少工具中有pipeline的概念,其實就是將多個流,經過pipe進行拼接,獲得一個有序的流序列,數據從一端寫入,依次進入每個流(一般是transform stream)中進行處理,並從最後一個流輸出。
流能夠是Object Mode和Buffering Mode兩種模式中的一種,不一樣模式的流能夠經過一些transform stream進行模式的轉換。框架
本文並非要講怎麼去實現一個Stream,只是闡述一些概念,以便理解,真正要實現一個Stream還要詳細閱讀Stream API的定義和規範,瞭解上述的概念以後會對本身實現一個Stream有所幫助。異步
上一節講了NodeJS的Stream API的基本概念,如今咱們講如下Gulp是如何利用Stream API的。
Gulp是一個基於流的構建工具,所以十分靈活,其API也十分簡單,就4個方法 src, dest, task, watch,分別用於輸入數據,輸出數據,定義任務,監控文件的變化並執行指定的任務。
Gulp自己只負責初始輸入和最終輸出,並提供了一個框架來管理任務,其實就連輸入輸出均可以不用Gulp來完成,這時候它就純粹至關於一個任務管理的角色。
在輸入輸出之間的各類具體任務都是經過第三方或者用戶自定義的流處理工具來完成的。
咱們會想,Gulp什麼都不作,爲何咱們還要用它,要用插件或者本身寫的話,還不如用功能豐富的webpack?其實Gulp比webpack靈活的地方在於用戶定義的Gulp任務自己就是跑在NodeJS上的JavaScript程序,跟普通的程序沒什麼兩樣,所以及其靈活;而Webpack內置的功能很豐富,用戶經過配置文件來指定其構建行爲,可是太多既定的規則和內置的功能,雖然可經過loader和plugin進行擴展,可是這些東西都是webpack特有的,也就是說這些擴展都被打上了‘webpack專用’的記號。
其實,Gulp的靈活性除了體如今使用Gulp其實就是在寫普通JavaScript程序這個事實以外,還體如今其能夠直接使用現有的工具來完成任務,例如Browserify等,而不須要特意爲這些工具開發」Gulp專用「的版本。Gulp的這個特性得益於其設計的虛擬文件格式與流的結合。
Gulp使用了Vinyl這種虛擬文件格式(github上的gulpjs/vinyl模塊),來用於其輸入輸出。Vinyl抽象了大多數文件系統中文件的屬性字段,例如文件名、路徑和修改日期等等;同時,Vinyl還將文件的內容抽象成了Buffer或者Stream。抽象的好處就是讓底層實際文件格式之間的差別,對上層透明,也就是說Gulp只認識Vinyl這種文件格式,咱們只要經過一些Adapter將其餘形式的文件(甚至不須要是真的文件,可能只是一個數據流或者一個Buffer)轉換成Vinyl格式,即可以被Gulp處理。理論上,對於任意現有的第三方工具,咱們只要Vinyl格式轉換成其能夠處理的格式,並將其輸出轉換成Vinyl格式,即可以在Gulp中使用,而因爲格式轉換的工做能夠交給獨立的轉換模塊來完成,因此咱們能夠不加修改就在Gulp中使用豐富的第三方工具來完成咱們的任務。
Gulp實際處理的是流,準確地講,是Object Mode的流,並且Object的類型是Vinyl。
在github中,咱們能夠看到一些Gulp專用工具的項目已經被廢棄,例如gulp-browserify,而推薦直接使用非Gulp專用版本的工具,例如node-browserify。開發和維護Gulp專用版本的工具費時費力,並且常常會出現落後於獨立工具版本的狀況,例如工具A已經到了3.0版本,可是Gulp專用的gulp-A中使用的A工具才2.5,跟不上主流。
下一節會介紹一些轉換Vinyl格式的工具。工具
以上都是我的學習總結出來的內容,理解和表述的專業性可能不強,做爲我的筆記,也但願能幫助到有須要的人。