i've organized my tasks in file like yours, but using ES6 import/export.
an example:
i've task clean, scripts and gulpfile.babel.js, the content is the following:
tasks/clean.js
:
import promisedDel from 'promised-del';
let cleanTaskCreator = (config) => {
let task = (done) => {
return promisedDel((typeof config.path === 'string' ? [config.dest] : config.dest));
};
task.displayName = 'clean:' + config.name;
task.description = 'clean task for ' + config.name;
return task;
};
export default cleanTaskCreator;
tasks/scripts.js
:
import gulp from 'gulp';
import named from 'vinyl-named';
import webpack from 'webpack-stream';
import {scripts as config} from '../config.js';
import clean from "./clean";
let scripts = () => {
return gulp.src(config.entries)
.pipe(named())
.pipe(webpack(config.webpackConfig))
.pipe(gulp.dest(config.dest));
};
scripts.displayName = 'scripts';
scripts.description = 'generation of scripts assets';
if(process.env.NODE_ENV !== 'production') {
let realScripts = scripts;
scripts = gulp.series(clean(config), realScripts);
scripts.displayName = 'clean&scripts';
scripts.description = 'clean scripts and ' + scripts.description;
}
export default scripts;
and finally the gulpfile.babel.js
:
import * as gulp from "gulp"
import scripts from "./gulp/tasks/scripts";
gulp.task(scripts);
let defaultTask = gulp.series(scripts);
defaultTask.displayName = 'default';
defaultTask.description = 'default';
gulp.task(defaultTask);
every task exposes a function to be executed, and internally define all its dependency (as you can see on task scripts, where if we are on production we clean the assets before generations).
Then, the main file, import only these functions and define the main task (classic default) and other tasks reachable from command line.
i'm not sure if this is the best mode (or the correct) for organize a project (big or small) with gulp4, but for me this layout is fine.
at the end, modules like gulp-load-subtasks not work on gulp4, because it load scripts in file name order (as you pointed out).