Итерирование по каталогам с помощью Gulp?
Я новичок в gulp, но мне интересно, можно ли его итерации по каталогам в задаче gulp.
Вот что я имею в виду, я знаю, что много учебников/демонстраций демонстрируют обработку кучи файлов JavaScript с использованием чего-то типа "**/*. js", а затем они скомпилируют его в один файл 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 файл.
Ответы
Ответ 1
Вот официальный рецепт этого: Создание файла для каждой папки
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);
});
Ответ 2
Вы можете использовать glob
, чтобы получить список каталогов и перебрать их, используя gulp.src
для создания отдельного конвейера для каждой функции. Затем вы можете вернуть обещание, которое разрешено, если все ваши потоки имеют end
ed.
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);
});
Ответ 3
Я пытаюсь понять, как работают потоки в node.
Я сделал простой пример для вас, как сделать поток для фильтрации папок и запустить для них новый поток.
'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 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
.
Попробуйте и дайте мне знать, если это сработает для вас.
Ответ 4
Сначала установите 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