2014-03-03 153 views
26

我是gulp的新手,但我想知道是否可以遍歷吞噬任務中的目錄。用Gulp遍歷目錄?

下面是我的意思,我知道很多教程/演示顯示使用類似「**/*。js」的方式處理一堆JavaScript文件,然後將它們編譯成單個JavaScript文件。但是我想迭代一組目錄,並將每個目錄編譯到它自己的JS文件中。

舉例來說,我有這樣的文件結構:

/js/feature1/something.js 
/js/feature1/else.js 
/js/feature1/foo/bar.js 
/js/feature1/foo/bar2.js 
/js/feature2/another-thing.js 
/js/feature2/yet-again.js 

......我想兩個文件:/js/feature1/feature1.min.js/js/feature2/feature2.min.js其中首先包含4個文件,第二個包含最後2個文件。

這是可能的,還是我將不得不手動添加這些目錄到清單?實際上迭代/js/內的所有目錄將是非常好的。

感謝您給我的任何幫助。

-Nate

編輯:應當指出的是,我不僅有2個目錄,但我有很多(也許10-20),所以我真的不希望寫一個任務每個目錄。我想以相同的方式處理每個目錄:獲取其中的所有JS(以及任何子目錄)並將其編譯爲基於特徵的縮小JS文件。

+0

[吞掉文件夾(https://www.npmjs.com/package/gulp-folders)似乎是一個選項 –

回答

37

有這種正式的食譜:Generating a file per folder

var fs = require('fs'); 
var path = require('path'); 
var merge = require('merge-stream'); 
var gulp = require('gulp'); 
var concat = require('gulp-concat'); 
var rename = require('gulp-rename'); 
var uglify = require('gulp-uglify'); 

var scriptsPath = 'src/scripts'; 

function getFolders(dir) { 
    return fs.readdirSync(dir) 
     .filter(function(file) { 
     return fs.statSync(path.join(dir, file)).isDirectory(); 
     }); 
} 

gulp.task('scripts', function() { 
    var folders = getFolders(scriptsPath); 

    var tasks = folders.map(function(folder) { 
     return gulp.src(path.join(scriptsPath, folder, '/**/*.js')) 
     // concat into foldername.js 
     .pipe(concat(folder + '.js')) 
     // write to output 
     .pipe(gulp.dest(scriptsPath)) 
     // minify 
     .pipe(uglify())  
     // rename to folder.min.js 
     .pipe(rename(folder + '.min.js')) 
     // write to output again 
     .pipe(gulp.dest(scriptsPath));  
    }); 

    // process all remaining files in scriptsPath root into main.js and main.min.js files 
    var root = gulp.src(path.join(scriptsPath, '/*.js')) 
     .pipe(concat('main.js')) 
     .pipe(gulp.dest(scriptsPath)) 
     .pipe(uglify()) 
     .pipe(rename('main.min.js')) 
     .pipe(gulp.dest(scriptsPath)); 

    return merge(tasks, root); 
}); 
+0

謝謝你指出這一點。我結束了一些非常相似的事情。 –

+0

@NathanRutman有機會看到你的'gulpfile.js'。我有同樣的問題,我不想重新發明車輪;) – Mirko

+0

這是否工作,如果我想編譯'scss'和'sass'文件? – SalahAdDin

0

首先,安裝gulp-concat & gulp-uglify

$ npm install gulp-concat 
$ npm install gulp-uglify 

接下來,做這樣的事情:

//task for building feature1 
gulp.task('minify-feature1', function() { 
return gulp.src('/js/feature1/*') 
    .pipe(uglify()) //minify feature1 stuff 
    .pipe(concat('feature1.min.js')) //concat into single file 
    .pipe(gulp.dest('/js/feature1')); //output to dir 
}); 

//task for building feature2 
gulp.task('minify-feature2', function() { //do the same for feature2 
return gulp.src('/js/feature2/*') 
    .pipe(uglify()) 
    .pipe(concat('feature2.min.js')) 
    .pipe(gulp.dest('/js/feature2')); 
}); 

//generic task for minifying features 
gulp.task('minify-features', ['minify-feature1', 'minify-feature2']); 

現在,所有你需要做的,從CLI運行如下的一切是:

$ gulp minify-features 
+1

你需要'return'來自兩個任務的管道,否則它們將同步運行,這意味着它們將在任務實際完成之前返回*。只需在'gulp.src'之前添加'return'即可。 – OverZealous

+0

謝謝@OverZealous。這促使我重新閱讀[gulp的異步文檔](https://github.com/gulpjs/gulp/blob/master/docs/API.md#async-task-support)。 – adamb

+1

@adamb這是我想避免的那種方法...說我有10或20個功能目錄...我不想寫20個任務,如果我能避免它...有沒有辦法做這種事情務實? –

15

你可以使用glob獲取列表的目錄並迭代它們,使用gulp.src爲每個特徵創建一個單獨的管道。然後,您可以返回一個承諾,當您的所有流都有end版本時,該承諾將被解決。

var fs = require('fs'); 
var Q = require('q'); 
var gulp = require('gulp'); 
var glob = require('glob'); 

gulp.task('minify-features', function() { 
    var promises = []; 

    glob.sync('/js/features/*').forEach(function(filePath) { 
    if (fs.statSync(filePath).isDirectory()) { 
     var defer = Q.defer(); 
     var pipeline = gulp.src(filePath + '/**/*.js') 
     .pipe(uglify()) 
     .pipe(concat(path.basename(filePath) + '.min.js')) 
     .pipe(gulp.dest(filePath)); 
     pipeline.on('end', function() { 
     defer.resolve(); 
     }); 
     promises.push(defer.promise); 
    } 
    }); 

    return Q.all(promises); 
}); 
4

我正在嘗試自己弄清流在節點中的工作方式。 我爲你做了一個簡單的例子,介紹如何製作一個流來過濾文件夾併爲它們開啓一個新的給定流。

'use strict'; 

var gulp    = require('gulp'), 
    es    = require('event-stream'), 
    log    = require('consologger'); 

// make a simple 'stream' that prints the path of whatever file it gets into 
var printFileNames = function(){ 

    return es.map(function(data, cb){ 

     log.data(data.path); 
     cb(null, data); 
    }); 
}; 

// make a stream that identifies if the given 'file' is a directory, and if so 
// it pipelines it with the stream given 
var forEachFolder = function(stream){ 

    return es.map(function(data, cb){ 

     if(data.isDirectory()){ 

      var pathToPass = data.path+'/*.*'; // change it to *.js if you want only js files for example 

      log.info('Piping files found in '+pathToPass); 

      if(stream !== undefined){ 
       gulp.src([pathToPass]) 
       .pipe(stream()); 
      } 
     } 

     cb(null, data); 
    }); 
}; 


// let's make a dummy task to test our streams 
gulp.task('dummy', function(){ 
    // load some folder with some subfolders inside 
    gulp.src('js/*') 
    .pipe(forEachFolder(printFileNames)); 
    // we should see all the file paths printed in the terminal 
}); 
你的情況

所以,你可以用你想用一個文件夾中的文件(如它們最小化和將它們連接起來),然後通過該流的一個實例到forEachFolder流我不管流製作。就像我對printFileNames自定義流一樣。

試一試,讓我知道它是否適合你。