成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Gulp思維——Gulp高級(jí)技巧

ad6623 / 1148人閱讀

摘要:我們創(chuàng)建一個(gè)可讀流,并嘗試使用和來(lái)進(jìn)行轉(zhuǎn)換,將最后得到的內(nèi)容交給。它重新使用可讀流中的文件名,然后在必要時(shí)創(chuàng)建文件夾使用。使用常規(guī)可讀流時(shí),你可以監(jiān)聽(tīng)事件來(lái)檢測(cè)數(shù)據(jù)碎片的到來(lái)不同的是,使用會(huì)將轉(zhuǎn)換成的文件對(duì)象重新寫(xiě)入到流中。

本文翻譯自Getting gulpy -- Advanced tips for using gulp.js

感受過(guò)gulp.js帶來(lái)的興奮過(guò)后,你需要的不僅僅是它的光鮮,而是切切實(shí)實(shí)的實(shí)例。這篇文章討論了一些使用gulp.js時(shí)常踩的坑,以及一些更加高級(jí)和定制化的插件和流的使用技巧。

基本任務(wù)

gulp的基本設(shè)置擁有非常友好的語(yǔ)法,讓你能夠非常方便的對(duì)文件進(jìn)行轉(zhuǎn)換:

gulp.task("scripts", function() {
    return gulp.src("./src/**/*.js")
        .pipe(uglify())
        .pipe(concat("all.min.js"))
        .pipe(gulp.dest("build/"));
});

這種方式能夠應(yīng)付絕大多數(shù)情況,但如果你需要更多的定制,很快就會(huì)遇到麻煩了。這篇將介紹這其中的一些情況并提供解決方案。

流不兼容?

使用gulp時(shí),你可能會(huì)陷入“流不兼容”的問(wèn)題。這主要是因?yàn)槌R?guī)流和Vinyl文件對(duì)象有差異,或是使用了僅支持buffer(不支持流)庫(kù)的gulp插件與常規(guī)流不兼容。

比如說(shuō),你不能直接將常規(guī)流與gulp和(或)gulp插件相連。我們創(chuàng)建一個(gè)可讀流,并嘗試使用gulp-uglify和gulp-rename來(lái)進(jìn)行轉(zhuǎn)換,將最后得到的內(nèi)容交給gulp.dest()。下面就是個(gè)錯(cuò)誤的例子:

var uglify = require("gulp-uglify"),
    rename = require("gulp-rename");
gulp.task("bundle", function() {
    return fs.createReadStream("app.js")
        .pipe(uglify())
        .pipe(rename("bundle.min.js"))
        .pipe(gulp.dest("dist/"));
});

為什么我們不能將可讀流和一個(gè)gulp插件直接相連?gulp難道不就是一個(gè)基于流的構(gòu)建系統(tǒng)嗎?是的,但上面的例子忽視了一個(gè)事實(shí),gulp插件期望的輸入是Vinyl文件對(duì)象。你不能直接將一個(gè)可讀流與一個(gè)以Vinyl文件對(duì)象作為輸入的函數(shù)(插件)相連

Vinyl文件對(duì)象

gulp使用了vinyl-fs,它實(shí)現(xiàn)了gulp.src()gulp.dest()方法。vinyl-fs使用vinyl文件對(duì)象——一種“虛擬文件格式”。如果我們需要將gulp和(或)gulp插件與常規(guī)的可讀流一起使用,我們就需要先把可讀流轉(zhuǎn)換為vinyl。

使用vinyl-source-stream是個(gè)不錯(cuò)的選擇,如下:

var source = require("vinyl-source-stream"),
    marked = require("gulp-marked");
fs.createReadStream("*.md")
    .pipe(source())
    .pipe(marked())
    .pipe(gulp.dest("dist/"));

另外一個(gè)例子首先通過(guò)browserify封裝并最終將其轉(zhuǎn)換為一個(gè)vinyl流:

var browserify = require("browserify"),
    uglify = require("gulp-uglify"),
    source = require("vinyl-source-stream");
gulp.task("bundle", function() {
    return browserify("./src/app.js")
        .bundle()
        .pipe(source(‘bundle.min.js))
        .pipe(uglify())
        .pipe(gulp.dest("dist/"));
});

哎呦不錯(cuò)哦。注意我們不再需要使用gulp-rename了,因?yàn)関inyl-source-stream創(chuàng)建了一個(gè)擁有指定文件名的vinyl文件實(shí)例(這樣gulp.dest方法將使用這個(gè)文件名)

gulp.dest

這個(gè)gulp方法創(chuàng)建了一個(gè)可寫(xiě)流,它真的很方便。它重新使用可讀流中的文件名,然后在必要時(shí)創(chuàng)建文件夾(使用mkdirp)。在寫(xiě)入操作完成后,你能夠繼續(xù)使用這個(gè)流(比如:你需要使用gzip壓縮數(shù)據(jù)并寫(xiě)入到其他文件)

流和buffer

既然你有興趣使用gulp,這篇文章假設(shè)你已經(jīng)了解了流的基礎(chǔ)知識(shí)。無(wú)論是buffer還是流,vinyl的虛擬文件都能包含在內(nèi)。使用常規(guī)可讀流時(shí),你可以監(jiān)聽(tīng)data事件來(lái)檢測(cè)數(shù)據(jù)碎片的到來(lái):

fs.createReadStream("/usr/share/dict/words").on("data", function(chunk) {
    console.log("Read %d bytes of data", chunk.length);
});
> Read 65536 bytes of data
> Read 65536 bytes of data
> Read 65536 bytes of data
> Read 65536 bytes of data
> ...

不同的是,使用gulp.src()會(huì)將轉(zhuǎn)換成buffer的vinyl文件對(duì)象重新寫(xiě)入到流中。也就是說(shuō),你獲得的不再是數(shù)據(jù)碎片,而是將內(nèi)容轉(zhuǎn)換成buffer后的(虛擬)文件。vinyl文件格式擁有一個(gè)屬性來(lái)表示里面是buffer還是流,gulp默認(rèn)使用buffer:

gulp.src("/usr/share/dict/words").on("data", function(file) {
    console.log("Read %d bytes of data", file.contents.length);
});
> Read 2493109 bytes of data

這個(gè)例子說(shuō)明了在文件被完整加入到流之前數(shù)據(jù)會(huì)被轉(zhuǎn)換成buffer。

Gulp默認(rèn)使用buffer

盡管更加推薦使用流中的數(shù)據(jù),但很多插件的底層庫(kù)使用的是buffer。有時(shí)候必須使用buffer,因?yàn)檗D(zhuǎn)換需要完整的文件內(nèi)容。比如文本替換和正則表達(dá)式的情形。如果使用數(shù)據(jù)碎片,將會(huì)面臨匹配失敗的風(fēng)險(xiǎn)。同樣,像UglifyJS和Traceur Compiler需要輸入完整的文件內(nèi)容(至少需要語(yǔ)法完整的JavaScript字符串)

這就是為什么gulp默認(rèn)使用轉(zhuǎn)換成buffer的流,因?yàn)檫@更好處理。

使用轉(zhuǎn)換成buffer的流也有缺點(diǎn),處理大文件時(shí)將非常低效。文件必須完全讀取,然后才能被加入到流中。那么問(wèn)題來(lái)了,文件的尺寸多大才會(huì)降低性能?對(duì)于普通的文本文件,比如JavaScript、CSS、模板等等,這些使用buffer開(kāi)銷(xiāo)非常小。

在任何情況下,如果將buffer選項(xiàng)設(shè)為false,你可以告訴gulp流中傳遞的內(nèi)容究竟是什么。如下所示:

gulp.src("/usr/share/dict/words", {buffer: false}).on("data", function(file) {
    var stream = file.contents;
    stream.on("data", function(chunk) {
        console.log("Read %d bytes of data", chunk.length);
    });
});
> Read 65536 bytes of data
> Read 65536 bytes of data
> Read 65536 bytes of data
> Read 65536 bytes of data
> ...
從流到buffer

由于所需的輸入(輸出)流和gulp插件不盡相同,你可能需要將流轉(zhuǎn)換成buffer(反之亦然)。之前已經(jīng)有過(guò)介紹,大多數(shù)插件使用buffer(盡管他們的一部分也支持流)。比如gulp-uglify和gulp-traceur。你可以通過(guò)gulp-buffer來(lái)轉(zhuǎn)換成buffer:

var source = require("vinyl-source-stream"),
    buffer = require("gulp-buffer"),
    uglify = require("gulp-uglify");
fs.createReadStream("./src/app.js")
    .pipe(source("app.min.js"))
    .pipe(buffer())
    .pipe(uglify())
    .pipe(gulp.dest("dist/"));

或者另一個(gè)例子:

var buffer = require("gulp-buffer"),
    traceur = require("gulp-traceur");
gulp.src("app.js", {buffer: false})
    .pipe(buffer())
    .pipe(traceur())
    .pipe(gulp.dest("dist/"));
將buffer轉(zhuǎn)換為流

你也可以使用gulp-streamify或gulp-stream將一個(gè)使用buffer的插件的輸出轉(zhuǎn)化為一個(gè)可讀流。這樣處理之后,跟在使用buffer的插件后面的(只能)使用流的插件也能正常工作了。

var wrap = require("gulp-wrap"),
    streamify = require("gulp-streamify"),
    uglify = require("gulp-uglify"),
    gzip = require("gulp-gzip");
gulp.src("app.js", {buffer: false})
    .pipe(wrap("(function(){<%= contents %>}());"))
    .pipe(streamify(uglify()))
    .pipe(gulp.dest("build"))
    .pipe(gzip())
    .pipe(gulp.dest("build"));
不是所有事都需要插件

雖然已經(jīng)有很多使用且方便的插件,很多任務(wù)以及轉(zhuǎn)換可以不使用插件而輕易完成。插件會(huì)帶來(lái)一些問(wèn)題,你需要依賴(lài)一個(gè)額外的npm模塊,一個(gè)插件接口和(反應(yīng)遲鈍?)的維護(hù)者,等等。如果一個(gè)任務(wù)可以不使用插件而使用原生模塊就能輕易完成,絕大多數(shù)情況下,都建議不要使用插件。能夠理解上面所說(shuō)的概念,并能夠在所處的情況下做出正確的決定,這點(diǎn)非常重要。下面來(lái)看一些例子:

vinyl-source-stream

之前的例子中,我們已經(jīng)直接使用了browserify,而不是使用(現(xiàn)已加入黑名單)gulp-browserify插件。這里的關(guān)鍵是使用vinyl-source-stream(或類(lèi)似的庫(kù))進(jìn)行加工,來(lái)將常規(guī)的可讀流輸入使用vinyl的插件。

文本轉(zhuǎn)換

另一個(gè)例子就是基于字符串的變換。這里有一個(gè)非常基礎(chǔ)的插件,直接使用了vinyl的buffer:

function modify(modifier) {
    return through2.obj(function(file, encoding, done) {
        var content = modifier(String(file.contents));
        file.contents = new Buffer(content);
        this.push(file);
        done();
    });
}

你可以像這樣使用這個(gè)插件:

gulp.task("modify", function() {
    return gulp.src("app.js")
        .pipe(modify(version))
        .pipe(modify(swapStuff))
        .pipe(gulp.dest("build"));
});
function version(data) {
    return data.replace(/__VERSION__/, pkg.version);
}
function swapStuff(data) {
    return data.replace(/(w+)s(w+)/, "$2, $1");
}

這個(gè)插件并沒(méi)有完成,而且也不能處理流(完整版本)。然而,這個(gè)例子說(shuō)明,可以很輕易地通過(guò)一些基本函數(shù)來(lái)創(chuàng)建新的變換。through2庫(kù)提供了非常優(yōu)秀的Node流封裝,并且允許像上面那樣使用轉(zhuǎn)換函數(shù)。

任務(wù)流程

如果你需要去運(yùn)行一些定制化或動(dòng)態(tài)的任務(wù),了解gulp所使用的Orchestrator模塊會(huì)很有幫助。gulp.add方法其實(shí)就是Orchestrator.add方法(事實(shí)上所有的方法都是從Orchestrator繼承而來(lái)的)。但為什么你需要這個(gè)?
* 你不想“私有任務(wù)”(比如:不暴露給命令行工具)弄亂gulp任務(wù)列表。
* 你需要更多的動(dòng)態(tài)的和(或)可重用的子任務(wù)。

最后的思考

請(qǐng)注意,gulp(或grunt)并不總是當(dāng)前情境下的最佳工具。比如說(shuō),如果你需要拼接并使用uglify壓縮一系列的JavaScript文件,又或者你需要編譯一些SASS文件,你可能需要考慮使用makefile或npm run,通過(guò)命令行來(lái)實(shí)現(xiàn)。減少依賴(lài),減少配置,才是正解。

閱讀通過(guò)npm run來(lái)實(shí)現(xiàn)任務(wù)自動(dòng)化來(lái)了解更多信息。你需要明確通過(guò)一系列的“自定義構(gòu)建”后需要得到什么,而哪個(gè)工具最合適。

不過(guò),我覺(jué)得gulp是一個(gè)偉大的構(gòu)建系統(tǒng),我很喜歡使用它,它展現(xiàn)了Node.js中流的強(qiáng)大。

希望這些能夠幫到你!如果你有任何反饋或其他提議,請(qǐng)?jiān)谠u(píng)論中告訴我,或者加我的twitter:@webprolific

小廣告:更多內(nèi)容歡迎來(lái)我的博客,共同探討

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/87638.html

相關(guān)文章

  • [Laya游戲開(kāi)發(fā)]小技巧使Laya構(gòu)建速度提高10倍

    摘要:為何選擇引擎微信小游戲推出之后,很多公司也相應(yīng)的進(jìn)入到微信小游戲這個(gè)領(lǐng)域,現(xiàn)在市場(chǎng)上的游戲開(kāi)發(fā)引擎,如都對(duì)小游戲有了很好的兼容性。 1. 為何選擇Laya引擎 微信小游戲推出之后,很多公司也相應(yīng)的進(jìn)入到微信小游戲這個(gè)領(lǐng)域,現(xiàn)在市場(chǎng)上的游戲開(kāi)發(fā)引擎,如Cocos、Egret、Laya都對(duì)小游戲有了很好的兼容性。目前公司技術(shù)棧主要是使用Cocos和Laya,經(jīng)過(guò)幾個(gè)項(xiàng)目的接觸,考量了引擎在...

    Harpsichord1207 評(píng)論0 收藏0
  • 個(gè)人分享--web前端學(xué)習(xí)資源分享

    摘要:前言月份開(kāi)始出沒(méi)社區(qū),現(xiàn)在差不多月了,按照工作的說(shuō)法,就是差不多過(guò)了三個(gè)月的試用期,準(zhǔn)備轉(zhuǎn)正了一般來(lái)說(shuō),差不多到了轉(zhuǎn)正的時(shí)候,會(huì)進(jìn)行總結(jié)或者分享會(huì)議那么今天我就把看過(guò)的一些學(xué)習(xí)資源主要是博客,博文推薦分享給大家。 1.前言 6月份開(kāi)始出沒(méi)社區(qū),現(xiàn)在差不多9月了,按照工作的說(shuō)法,就是差不多過(guò)了三個(gè)月的試用期,準(zhǔn)備轉(zhuǎn)正了!一般來(lái)說(shuō),差不多到了轉(zhuǎn)正的時(shí)候,會(huì)進(jìn)行總結(jié)或者分享會(huì)議!那么今天我就...

    sherlock221 評(píng)論0 收藏0
  • Vue ES6 Jade Scss Webpack Gulp

    摘要:主有前端后端,并加,各一名。本著工欲善其事,必先利其器的理念,一直以來(lái)在工作效率這塊,略懷執(zhí)念一個(gè)問(wèn)題不應(yīng)該被解決兩次。下圖為開(kāi)發(fā)項(xiàng)目機(jī)制所涉及到的插件工欲善其事,必先利其器,語(yǔ)言,框架皆可以歸結(jié)為器而不當(dāng)僅局限于開(kāi)發(fā)工具以及機(jī)。 原文鏈接: http://www.jeffjade.com/2016/05/08/106-vue-es6-jade-scss-webpack-gulp/ 一...

    rickchen 評(píng)論0 收藏0
  • 重讀 Gulp

    摘要:當(dāng)接收一個(gè)回調(diào)函數(shù)的時(shí)候,一定要注意回調(diào)函數(shù)中的參數(shù)。主要作用就是用來(lái)讀取文件或者文件夾中的數(shù)據(jù)。表示文件的名稱(chēng)指的是發(fā)生的變化使用技巧的進(jìn)一步使用,可以參照中文官網(wǎng)中的技巧集。 Gulp 簡(jiǎn)介 Gulp 對(duì)現(xiàn)在的前端而言,是一個(gè)稍微老舊的工具了,但是,為了復(fù)習(xí)以前學(xué)過(guò)的內(nèi)容,還是把它翻出來(lái),放在自己的博客中。說(shuō)不定哪天又用到了呢。 需要說(shuō)明的是,這里使用的 Gulp 版本是 3.9....

    vpants 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<