Gulp學習筆記

一逗宜、Grunt Gulp區(qū)別

參考
Grunt 新手一日入門
gulp VS grunt
Grunt 就是小明想的這樣一種自動化任務處理工具奶段,它就是一個工具框架澎胡,有很多插件擴展它的功能垦垂。Grunt 基于 Node.js 沪哺,用 JS 開發(fā)隅俘,這樣就可以借助 Node.js 實現(xiàn)跨系統(tǒng)跨平臺的桌面端的操作邻奠,例如文件操作等等。此外为居,Grunt 以及它的插件們碌宴,都作為一個 包 ,可以用 NPM 安裝進行管理蒙畴。所以 NPM 生成的package.json 項目文件贰镣,里面可以記錄當前項目中用到的 Grunt 插件,而 Grunt 會調用 Gruntfile.js 這個文件膳凝,解析里面的任務(task)并執(zhí)行相應操作碑隆。

需要注意,因為使用 -g 命令會安裝到全局蹬音,可能會涉及到系統(tǒng)敏感目錄上煤,如果用 Windows 的話,可能需要你用管理員權限著淆,如果用 OS X / Linux 的話劫狠,你可能需要加上 sudo 命令。

除了 Grunt 之外永部,同類型比較火的還有 Gulp 這個工具独泞。其實兩個東西的功能是一樣的,只不過是任務配置 JS 的語法不同苔埋,Gulp 的 Gulpfile.js 的寫法更加通俗易懂懦砂,上手更快。但是 Gulp 的插件等感覺不如 Grunt,Grunt 官方提供了一些常見的插件孕惜,滿足大部分日常工作愧薛,而且可靠值得信賴,而 Gulp 好像沒有太多官方出品衫画,各種插件不太規(guī)范毫炉。簡單的說,Grunt 和 Gulp 就像 iPhone 與 Android 一樣削罩,一個質量高學習難一點瞄勾,一個學起來簡單但是有點那個,你懂得弥激。

二进陡、Gulp使用簡記

參考
gulp詳細入門教程
前端構建工具gulpjs的使用介紹及技巧
Gulp折騰之路(II)

1.gulp的全局安裝和本地安裝
首先確保你已經正確安裝了nodejs環(huán)境。使用cnpm init生成package.json,然后以全局方式安裝gulp:
npm install -g gulp
全局安裝gulp后微服,還需要在每個要使用gulp的項目中都單獨安裝一次趾疚。把目錄切換到你的項目文件夾中,然后在命令行中執(zhí)行:
npm install gulp
如果想在安裝的時候把gulp寫進項目package.json文件的依賴中以蕴,則可以加上--save-dev:
npm install --save-dev gulp
這樣就完成了gulp的安裝糙麦。至于為什么在全局安裝gulp后,還需要在項目中本地安裝一次丛肮,有興趣的可以看下stackoverflow上有人做出的回答:why-do-we-need-to-install-gulp-globally-and-locally
赡磅、what-is-the-point-of-double-install-in-gulp滞项。大體就是為了版本的靈活性眷射,但如果沒理解那也不必太去糾結這個問題,只需要知道通常我們是要這樣做就行了撤防。
細心的你可能會發(fā)現(xiàn)习劫,我們全局安裝了gulp咆瘟,項目也安裝了gulp,全局安裝gulp是為了執(zhí)行gulp任務榜聂,本地安裝gulp則是為了調用gulp插件的功能搞疗。
如果已經有了package.json卻沒有node_modules文件夾,可以直接運行cnpm install來恢復

生成package.json

安裝gulp 和gulp插件

2.開始使用gulp
2.1 建立gulpfile.js文件
就像gruntjs需要一個Gruntfile.js文件一樣须肆,gulp也需要一個文件作為它的主文件匿乃,在gulp中這個文件叫做gulpfile.js。新建一個文件名為gulpfile.js的文件豌汇,然后放到你的項目目錄中幢炸。之后要做的事情就是在gulpfile.js文件中定義我們的任務了。下面是一個最簡單的gulpfile.js文件內容示例拒贱,它定義了一個默認的任務宛徊。

var gulp = require('gulp');
gulp.task('default',function(){
    console.log('hello world');
});

此時我們的目錄結構是這樣子的:

├── gulpfile.js
├── node_modules
│ └── gulp
└── package.json

2.2 運行gulp任務
要運行gulp任務佛嬉,只需切換到存放gulpfile.js文件的目錄(windows平臺請使用cmd或者Power Shell等工具),然后在命令行中執(zhí)行gulp命令就行了闸天,gulp后面可以加上要執(zhí)行的任務名暖呕,例如gulp task1,如果沒有指定任務名苞氮,則會執(zhí)行任務名為default的默認任務湾揽。
3、gulp的API介紹
使用gulp笼吟,僅需知道4個API即可:gulp.task(),gulp.src(),gulp.dest(),gulp.watch()
3.1 gulp.src()

//使用數(shù)組的方式來匹配多種文件
gulp.src(['js/*.js','css/*.css','*.html'])
gulp.src([*.js,'!b*.js']) //匹配所有js文件库物,但排除掉以b開頭的js文件

3.2 gulp.dest()
gulp.dest(path)生成的文件路徑是我們傳入的path參數(shù)后面再加上gulp.src()中有通配符開始出現(xiàn)的那部分路徑。

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()方法中配置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    

看我自己的例子,為了復制過來空猜,仍然保持libs/min的文件夾路徑

//直接復制的文件,必須是bin/libs/min下的JS
var copyLibsMinSrc = [
    // 'libs/min/vconsole.min.js',
    'libs/min/socket.io.min.js'
];
gulp.task('copyLibsMin', function() {
    for(var i = 0; i < copyLibsMinSrc.length; i ++){
        copyLibsMinSrc[i] = options.binPath + '/' + copyLibsMinSrc[i];
    }
    gulp.src(copyLibsMinSrc,{base:options.binPath + '/'})
    .pipe(gulp.dest(options.releasePath));
});

另外绽慈,在我發(fā)布版本的時候,去config.js里讀取當前版本號辈毯,然后自增1作為發(fā)布版本號坝疼。而且發(fā)布完成后,發(fā)布出來的config.js和項目里原來的config.js的版本號值都要變成最新的谆沃。也就是出現(xiàn)一個新需求钝凶,如何用Gulp更改原文件?
參考
使用gulp replace怎么替換原文件唁影,而不是生成新文件耕陷?
Can Gulp overwrite all src files?
我使用了第一種方式:{base:'./'}

  gulp.src(options.binPath+'/'+options.configFile,{base:'./'})
  .pipe(replace(/version:\".*\"/gi, 'version:\"'+options.version+'\"'))
  .pipe(gulp.dest(''));

3.3 gulp.task()
gulp.task方法用來定義任務

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

關于異步,原文提供了三種方法据沈,其中第一種比較方便:在異步操作完成后執(zhí)行一個回調函數(shù)來通知gulp這個異步任務已經完成,這個回調函數(shù)就是任務函數(shù)的第一個參數(shù)哟沫,也就是例子中的cb

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

//two任務雖然依賴于one任務,但并不會等到one任務中的異步操作完成后再執(zhí)行
gulp.task('two',['one'],function(){
  console.log('two is done');
});

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

3.4 gulp.watch()
gulp.watch()用來監(jiān)視文件的變化,當文件發(fā)生變化后锌介,我們可以利用它來執(zhí)行相應的任務嗜诀,例如文件壓縮等猾警。

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

第一個參數(shù)glob 為要監(jiān)視的文件匹配模式,規(guī)則和用法與 gulp.src() 方法中的 glob 相同隆敢。
上面是使用tasks方式发皿,還可以使用回調函數(shù)的方式

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

關于插件watchify穴墅,參考Browserify + watchify

三、gulp常用插件

安裝插件例子:cnpm i -D gulp-zip//–save-dev可以簡寫成-D
參考
gulp自動化打包(上)
gulp自動化打包(下)
精通gulp常用插件
常用gulp插件介紹(一)
常用gulp插件介紹(二)

1.合并壓縮 gulp-concat gulp-uglify

var gulp = require('gulp');
var concat = require("gulp-concat");
var uglify = require('gulp-uglify');
gulp.task('concat', function() {
    gulp.src(['js/*.js','!js/ui/layaUI.max.all.js'])  //要合并的文件
    //gulp.src(['js/APage.js','js/BPage.js'])  //要合并的文件
    .pipe(concat('all.js'))  // 合并匹配到的js文件并命名為 "all.js"
    //.pipe(uglify())
    .pipe(gulp.dest('dest'));
});

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

uglify()可以傳入參數(shù)匣屡,比如

gulp.task('minimize', ['lint', 'build'], function () {
    let options = {
        sourceMap: true,
        sourceMapIncludeSources: true,
        sourceMapRoot: './src/',
        mangle: true,
        compress: {
            sequences: true,
            dead_code: true,
            conditionals: true,
            booleans: true,
            unused: true,
            if_return: true,
            join_vars: true
        }
    };

    return gulp.src('dist/flv.js')
        .pipe(rename({extname: '.min.js'}))
        .pipe(sourcemaps.init({loadMaps: true}))
            .pipe(uglify(options))
            .on('error', console.error.bind(console))
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest('./dist/'));
});

具體參數(shù)含義參考UglifyJS中文文檔

2.建服務器gulp-connect
用 gulp 建一個服務器
用gulp建立一個服務器

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

gulp.task('webserver', function() {
    connect.server({port:'9000'});
    //connect.server({root:'../BGH5Video/bin',port:'9000'});
});

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

不過封救,還是沒有anywhere方便
3.文件內容修改gulp-replace

gulp.task("replace", function () {
    var date = new Date().getTime();
    gulp.src('../main.html')
        .pipe(replace(/_VERSION_/gi, date))
        .pipe(gulp.dest(option.buildPath + '/'))
})

//main.html文件
<!DOCTYPE html>
<html ng-app="app">
<head lang="en">
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
    <meta name="format-detection" content="telephone=no"/>
    <link rel="stylesheet" href="style/base.css?v=_VERSION_"/>
    <link rel="stylesheet" href="style/index.css?v=_VERSION_"/>
</head>
<body>
<ui-view></ui-view>
</body>
<script src="js/config/config.js?v=_VERSION_"></script>
<script src="js/app.js?v=_VERSION_"></script>
<script src="js/service/TrackDataService.js?v=_VERSION_"></script>
<script src="js/service/APIService.js?v=_VERSION_"></script>
<script src="js/service/DService.js?v=_VERSION_"></script>
<script src="js/controllers/indexCtrl.js?v=_VERSION_"></script>
<script src="js/directive/lazy.js?v=_VERSION_"></script>
<script src="js/directive/slider.js?v=_VERSION_"></script>
<script src="js/filter/filters.js?v=_VERSION_"></script>
</html>

另外參考將 buffer 變?yōu)?stream (內存中的內容)

4.gulp git
下面是一段獲取git倉庫中tag為v1.0.0的代碼(也可以checkout分支名):

var git = require('gulp-git');
gulp.task('checkout', function () {
  git.checkout('v1.0.0', function (err) {
    if (err) throw err;
  });
})

5.gulp-htmlmin
就是一個壓縮html的插件捣作,沒什么特別要講的誉结,這邊也直接拿網上的一個常用配置來演示。

var htmlmin = require('gulp-htmlmin');
gulp.task('testHtmlmin', function () {
    var options = {
        removeComments: true,//清除HTML注釋
        collapseWhitespace: true,//壓縮HTML
        collapseBooleanAttributes: true,//省略布爾屬性的值 <input checked="true"/> ==> <input />
        removeEmptyAttributes: true,//刪除所有空格作屬性值 <input id="" /> ==> <input />
        removeScriptTypeAttributes: true,//刪除<script>的type="text/javascript"
        removeStyleLinkTypeAttributes: true,//刪除<style>和<link>的type="text/css"
        minifyJS: true,//壓縮頁面JS
        minifyCSS: true//壓縮頁面CSS
    };
    gulp.src('src/html/*.html')
        .pipe(htmlmin(options))
        .pipe(gulp.dest('dist/html'));
});

6.minimistyargs
參考 minimist輕量級的命令行參數(shù)解析引擎
這個插件券躁,簡單來說就是從命令行當中提取參數(shù)惩坑。
開發(fā)中經常會遇到的應用場景是提供不同的參數(shù),即動態(tài)參數(shù)也拜,對應到gulp中以舒,如果我們需要在命令行中手動輸入某個參數(shù),此時就可以用minimist把他從命令行“提取”出來慢哈。

var argv = require('minimist')(process.argv.slice(2));
gulp.task('checkout', function () {
 var gitTag = argv.tag;
  git.checkout(gitTag, function (err) {
    if (err) throw err;
  });
})

cmd中輸入gulp checkout --tag v1.0.0
文檔解釋也是一個‘-’為key,之后為value蔓钟。但個人實際操作為兩個‘-’為key。
此時卵贱,gitTag就會被賦值為v1.0.0滥沫。
關于process.argv,參考Node.js process.argv
以下例子參考gulp中文網-從命令行傳遞參數(shù)

// npm install --save-dev gulp gulp-if gulp-uglify minimist

var gulp = require('gulp');
var gulpif = require('gulp-if');
var uglify = require('gulp-uglify');

var minimist = require('minimist');

var knownOptions = {
  string: 'env',
  default: { env: process.env.NODE_ENV || 'production' }
};

var options = minimist(process.argv.slice(2), knownOptions);

gulp.task('scripts', function() {
  return gulp.src('**/*.js')
    .pipe(gulpif(options.env === 'production', uglify())) // 僅在生產環(huán)境時候進行壓縮
    .pipe(gulp.dest('dist'));
});
然后键俱,通過如下命令運行 gulp:
$ gulp scripts --env development

7.gulp-del
刪除目標目錄兰绣,目標文件

var del=require('gulp-del')
gulp.task('clean',function(){
return del(config.dist.basePath);
})

另外,參考gulp中文網-刪除文件和文件夾
你也許會想要在編譯文件之前刪除一些文件编振。由于刪除文件和文件內容并沒有太大關系缀辩,所以,我們沒必要去用一個 gulp 插件踪央。最好的一個選擇就是使用一個原生的 node 模塊臀玄。
因為 del 模塊支持多個文件以及 globbing,因此杯瞻,在這個例子中镐牺,我們將使用它來刪除文件:
$ npm install --save-dev del
假想有如下的文件結構:

.
├── dist
│   ├── report.csv
│   ├── desktop
│   └── mobile
│       ├── app.js
│       ├── deploy.json
│       └── index.html
└── src

在 gulpfile 中,我們希望在運行我們的編譯任務之前魁莉,將 mobile 文件的內容先清理掉:

var gulp = require('gulp');
var del = require('del');

gulp.task('clean:mobile', function (cb) {
  del([
    'dist/report.csv',
    // 這里我們使用一個通配模式來匹配 `mobile` 文件夾中的所有東西
    'dist/mobile/**/*',
    // 我們不希望刪掉這個文件睬涧,所以我們取反這個匹配模式
    '!dist/mobile/deploy.json'
  ], cb);
});

gulp.task('default', ['clean:mobile']);

8.gulp-zip
將src中的各種文件募胃,打成一個zip包,演示代碼:

var zip = require('gulp-zip');
gulp.task('zip', ()  {
         gulp.src('src/*')
        .pipe(zip('zipName.zip'))
        .pipe(gulp.dest('dist'));
});

9.gulp-ftp
將目標文件畦浓,發(fā)送至FTP服務器痹束,這邊有5個參數(shù)是必填的,分別為:
host:服務器地址(必須)
port:服務器端口(必須)
user:ftp賬戶(必須) // 如果FTP沒有訪問限制讶请,可以不填
pass:ftp賬戶密碼(必須)// 如果FTP沒有訪問限制祷嘶,可以不填
remote: 對應的服務器文件地址(必須)
logger:輸出文件列表名稱,默認在項目根目錄生成文件(可選,默認:logger.txt)
froot: 提單文件前綴(可選,默認:/usr/local/imgcache/htdocs)
exp:體驗環(huán)境地址(可選夺溢,默認null)
pro:正式環(huán)境地址(可選论巍,默認null)

gulp.task('ftp', function () {
  return gulp.src("dist_zip/*")
    .pipe(ftp({
      host: 'testHost',
      port: 21,
      //user: 'anonymous',
      //pass:null,
      remotePath: "path/"
    }));
});

10.run-sequence
一個串行方式跑gulp任務的插件,在實際場景中风响,不允許我們同時跑很多任務嘉汰,因為任務之間往往是相互依賴的,此時run-sequence就是一個很好的選擇状勤,他可以讓多個任務按照寫入順序執(zhí)行鞋怀,同時可以控制哪些任務并行跑持搜,哪些按照順序跑密似。

 var runSequence = require('run-sequence');
gulp.task('publish', function (callback) {
  runSequence('clean',['html', 'js','less', 'copy'],'zip_new',callback);
});

比如上述代碼葫盼,執(zhí)行順序為1残腌、'clean'。2贫导、['html', 'js','less', 'copy']废累。3、'zip_new'脱盲。
當然也可以在gulp中使用依賴注入的方法。比如:

gulp.task('two', ['one'], function() {
    //任務two,會在任務one結束之后執(zhí)行
});

但個人還是更喜歡日缨,用run-sequence因為一旦依賴項變多之后钱反,普通的注入,相互之間依賴過后匣距,可讀性就會變差面哥,而sequence會讓代碼看起來更優(yōu)雅,寫起來也更簡單毅待。

gulp.task('publish', function (callback) {
  runSequence(['html', 'js','less', 'copy'],'zip_new',ftp,callback);
});

這里有兩點需要注意:
a.run-sequence里面的任務尚卫,按順序執(zhí)行(方括號里面4個任務,算作一個任務)尸红,而且前一個跑完才會跑后一個吱涉,方括號里的是異步的刹泄,即不一定哪個先完成。
b.要想達到第一點里面的同步執(zhí)行(一個任務完成才開始下一個)怎爵,一定要保證前面的所有任務特石,即除了ftp任務,其余的方法一定要是return出來的(but make sure they either return a stream or promise, or handle the callback)鳖链,即:
正確寫法:

 gulp.task('js', function (done) {
  return gulp.src(config.input.js)
    .pipe(ngAnnotate({single_quotes: true}))
    .pipe(uglify())
    .pipe(concat('index.min.js'))
    .pipe(gulp.dest(config.output.dist))
});
錯誤寫法:

 gulp.task('js', function (done) {
  gulp.src(config.input.js)
    .pipe(ngAnnotate({single_quotes: true}))
    .pipe(uglify())
    .pipe(concat('index.min.js'))
    .pipe(gulp.dest(config.output.dist))
});

前邊都要這樣寫姆蘸,最后一項不加return,在本例中芙委,即ftp的方法不用返回
關于并行串行逞敷,可以參考gulp- run-sequence
另外,我在實際使用中發(fā)現(xiàn)如果是讀取文件配置后再做某些操作灌侣,用sequence不行推捐,原因不明。最后還是用了回調.

  1. 圖片壓縮顶瞳,參考Laya 圖片壓縮(pngquant,tinypng,limitPNG)

12.gulp-rename
描述:重命名文件玖姑。

var rename = require("gulp-rename");

gulp.src('./hello.txt')
  .pipe(rename('gb/goodbye.md'))    // 直接修改文件名和路徑
  .pipe(gulp.dest('./dist')); 
 
gulp.src('./hello.txt')
  .pipe(rename({
    dirname: "text",                // 路徑名
    basename: "goodbye",            // 主文件名
    prefix: "pre-",                 // 前綴
    suffix: "-min",                 // 后綴
    extname: ".html"                // 擴展名
  }))
  .pipe(gulp.dest('./dist'));

13.gulp-filter
描述:在虛擬文件流中過濾文件。

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

const f = filter(['**', '!*/index.js']);
gulp.src('js/**/*.js')
    .pipe(f)                        // 過濾掉index.js這個文件
    .pipe(gulp.dest('dist'));

const f1 = filter(['**', '!*/index.js'], {restore: true});
gulp.src('js/**/*.js')
    .pipe(f1)                       // 過濾掉index.js這個文件
    .pipe(uglify())                 // 對其他文件進行壓縮
    .pipe(f1.restore)               // 返回到未過濾執(zhí)行的所有文件
    .pipe(gulp.dest('dist'));       // 再對所有文件操作慨菱,包括index.js

14.gulp-if
描述:有條件地運行一個任務焰络。

var gulpif = require('gulp-if');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var condition = true; 

gulp.src('./js/*.js')
    // condition為true時執(zhí)行uglify(), else 執(zhí)行concat('all.js')
    .pipe(gulpif(condition, uglify(), concat('all.js')))
    .pipe(gulp.dest('./dist/'));

15.gulp-filtergulp-if符喝、gulp-ignore區(qū)別使用
參考gulp排除已壓縮文件思路

  1. gulp-base64
    參考Gulp系列教程:圖片轉換成Base64編碼
body {
  background-color: #fdfdfd;
  background-image: url("/assets/images/patterns/light_grey.png");
  background-size: 301px 621px;
}
任務運行后闪彼,CSS如下:

body {
  background-color: #fdfdfd;
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAloAAATaBAMAAAB4FdU7AAAAFVBM...);
  background-size: 301px 621px;
}

//gulp/config.js 

base64: {
  src: developmentAssets + '/css/*.css',
  dest: developmentAssets + '/css',
  options: {
    baseDir: build,
    extensions: ['png'],
    maxImageSize: 20 * 1024, // bytes
    debug: false
  }
}
我只替換了小于20KB的PNG。這樣高分辨率圖不會嵌入CSS中协饲。

// gulp/tasks/development/base64.js

var gulp   = require('gulp');
var base64 = require('gulp-base64');
var config = require('../../config').base64;

/**
 * Replace urls in CSS fies with base64 encoded data
 */
gulp.task('base64', ['sass'], function() {
  return gulp.src(config.src)
    .pipe(base64(config.options))
    .pipe(gulp.dest(config.dest));
});

17.gulp util

var gutil = require('gulp-util');
 //gulp多功能的插件畏腕,可以替換擴展名,log顏色日志茉稠,模板
gutil.log( gutil.colors.red(i) ,  gutil.colors.green("已經處理完畢描馅!"));
  1. gulp-print
    這個插件的作用很簡單,打印出stream里面的所有文件名而线,通常調試的時候比較需要铭污。

19.gulp-bytediff
這是一個統(tǒng)計文件大小變化的工具,通常與壓縮類工具放在一起實用膀篮,比如

gulp.src('**/*.html')
    .pipe($.bytediff.start())
    .pipe($.minifyHtml({empty: true}))
    .pipe($.bytediff.stop(bytediffFormatter))
    .pipe(gulp.dest('dist'));
function bytediffFormatter (data) {
    var difference = (data.savings > 0) ? ' smaller.' : ' larger.';
    return data.fileName + ' went from ' +
        (data.startSize / 1000).toFixed(2) + ' kB to ' +
        (data.endSize / 1000).toFixed(2) + ' kB and is ' +
        formatPercent(1 - data.percent, 2) + '%' + difference;
}

在壓縮的pipe前后加上.bytediff.start()和.bytediff.stop(callback)嘹狞,即可統(tǒng)計壓縮前后文件的變化。在callback中傳入的參數(shù)data上誓竿,可以訪問到很多變量磅网,如文件名,變化前后的大小筷屡,變化百分比等等涧偷。

20.gulp-flatten
比如gulp.src('*/.js')匹配了很多文件簸喂,包括a/b/c.js,d/e.js嫂丙,f/g/h/i/j/k.js娘赴,l.js,這些文件的層級都不一樣跟啤,一旦我們將這個文件pipe給$.flatten()诽表,則所有的文件夾層級都會去掉,最終的文件將是c.js隅肥,e.js竿奏,k.js,l.js腥放,在一些場景下還是非常有用的泛啸。

21.gulp-order
gulp在合并js文件時,需要注意合并的順序秃症,可以使用gulp-order插件

var gp = require('gulp');
var concat = require('gulp-concat');
var order = require("gulp-order");

gp.task("minifyJs", function(){
    gp.src('./scripts/*.js')
    .pipe(order([
        'scripts/1.js',
        'scripts/2.js',
        'scripts/3.js',
        'scripts/*.js'
    ]))
    .pipe(concat('main.js'))
    .pipe(gp.dest('./dist/js'));
});

注意:order中的js路徑不要包含 ./ 否則會報錯

22.gulp-sourcemaps
參考
gulp-sourcemaps的用法
SourceMap 使用教程

// 引入gulp
var gulp = require('gulp');
// 引入gulp-concat插件
var concat = require('gulp-concat');
// 引入gulp-uglify插件
var uglify = require('gulp-uglify');
// 引入gulp-sourcemaps插件
var sourceMap = require('gulp-sourcemaps');

gulp.task('sourcemap',function() {
    gulp.src('./src/*.js')  
    .pipe( sourceMap.init() )
    .pipe( concat('all.js') )  
    .pipe( uglify() )  
    .pipe( sourceMap.write('../maps/',{addComment: false}) )
    .pipe( gulp.dest('./dist/') ) 
})
sourcemaps.init({
      loadMaps: true,  //是否加載以前的 .map 
      largeFile: true,   //是否以流的方式處理大文件
})

sourceMap.write( path )候址,將會在指定的 path,生成獨立的sourcemaps信息文件种柑。如果指定的是相對路徑岗仑,是相對于 all.js 的路徑。無法指定路徑為 src 目錄聚请,否則荠雕,sourcemaps文件會生成在 dist 目錄下。

addComment : true / false ; 是控制處理后的文件(本例是 all.js )驶赏,尾部是否顯示關于sourcemaps信息的注釋炸卑。不加這個屬性,默認是true煤傍。設置為false的話盖文,就是不顯示。

四蚯姆、結合cmd

1.接受參數(shù)
參考CMD接受輸入參數(shù)(定時關機小例子)

@echo off  
set /p time=請輸入關機時間:  
shutdown -s -f -t %time%

@echo off 椅寺,DOS會依次執(zhí)行文件中的命令,并將執(zhí)行的命令自動輸出在DOS中蒋失,如果我們不想將執(zhí)行的命令顯示出來,就可以使用echo off來關閉自動輸出桐玻。但是篙挽,echo off本身也是一條命令,也會顯示出來镊靴,如果我們連echo off都不想顯示铣卡,那就要在echo off前面加上@链韭。所以總的來說,這條命令的作用就是煮落,關閉執(zhí)行命令的輸出敞峭。
@set /p time=請輸入關機時間:,set /p varName="string"蝉仇, 的作用是定義一個變量旋讹,變量的值讓用戶輸入,后面的字符串string轿衔,是顯示在命令窗口中的提示沉迹。
%time%,獲取變量的值

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末害驹,一起剝皮案震驚了整個濱河市鞭呕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宛官,老刑警劉巖葫松,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異底洗,居然都是意外死亡腋么,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門枷恕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來党晋,“玉大人,你說我怎么就攤上這事徐块∥床#” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵胡控,是天一觀的道長扳剿。 經常有香客問我,道長昼激,這世上最難降的妖魔是什么庇绽? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮橙困,結果婚禮上瞧掺,老公的妹妹穿的比我還像新娘。我一直安慰自己凡傅,他們只是感情好辟狈,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般哼转。 火紅的嫁衣襯著肌膚如雪明未。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天壹蔓,我揣著相機與錄音趟妥,去河邊找鬼。 笑死佣蓉,一個胖子當著我的面吹牛披摄,可吹牛的內容都是我干的。 我是一名探鬼主播偏螺,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼行疏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了套像?” 一聲冷哼從身側響起酿联,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎夺巩,沒想到半個月后贞让,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡柳譬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年喳张,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片美澳。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡销部,死狀恐怖,靈堂內的尸體忽然破棺而出制跟,到底是詐尸還是另有隱情舅桩,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布雨膨,位于F島的核電站擂涛,受9級特大地震影響,放射性物質發(fā)生泄漏聊记。R本人自食惡果不足惜撒妈,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望排监。 院中可真熱鬧狰右,春花似錦、人聲如沸舆床。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至附鸽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瞒瘸,已是汗流浹背坷备。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留情臭,地道東北人省撑。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像俯在,于是被迫代替她去往敵國和親竟秫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內容

  • gulpjs是一個前端構建工具跷乐,與gruntjs相比肥败,gulpjs無需寫一大堆繁雜的配置參數(shù),API也非常簡單愕提,學...
    依依玖玥閱讀 3,149評論 7 55
  • 對網站資源進行優(yōu)化馒稍,并使用不同瀏覽器測試并不是網站設計過程中最有意思的部分,但是這個過程中的很多重復的任務能夠使用...
    懵逼js閱讀 1,061評論 0 8
  • gulpjs是一個前端構建工具浅侨,與gruntjs相比纽谒,gulpjs無需寫一大堆繁雜的配置參數(shù),API也非常簡單如输,學...
    小裁縫sun閱讀 922評論 0 3
  • gulpjs是一個前端構建工具鼓黔,與gruntjs相比,gulpjs無需寫一大堆繁雜的配置參數(shù)不见,API也非常簡單澳化,學...
    build1024閱讀 527評論 0 0
  • 1、gulp的安裝 首先確保你已經正確安裝了nodejs環(huán)境脖祈。然后以全局方式安裝gulp: npm install...
    F_imok閱讀 2,364評論 1 11