gulpjs / gulp

A toolkit to automate & enhance your workflow
https://gulpjs.com
MIT License
33.01k stars 4.23k forks source link

[gulp 4] allow forward references to tasks #802

Closed alvint closed 9 years ago

alvint commented 9 years ago

Currently, forward references to tasks do not work in gulp 4 (and gulp 3, but I don't care about that):

gulp.task('default', gulp.series('clean', 'build', 'watch', 'server'));

gulp.task('clean', function () {
    // do something
});
...

This results in AssertionError: Task never defined: clean.

From a stylistic standpoint, many people prefer to place the broadest tasks first and then define component tasks later, since this is how most people think and design code. Also the current 'bottom up', Forth-like restriction is no longer necessary considering how gulp 4 works.

From a design standpoint, since tasks are interchangeable with functions now, and since functions (like most stuff in Javascript) can be referenced from anywhere within the current scope regardless of where it was declared, to be consistent tasks should work the same way.

yocontra commented 9 years ago

I agree with @geekflyer (I think I said this earlier too) - runtime lookups will make organizing gulpfiles into multiple files wayyy easier but it isn't the only way to do it.

heikki commented 9 years ago

ES6 module syntax looks interesting if it's available some day. There's named and default exports. http://24ways.org/2014/javascript-modules-the-es6-way

sttk commented 9 years ago

I made a module to allow forward references to tasks againt this Issue.

It stores the task names and the arguments of gulp.series/.parallel functions when they failed, and try to define the tasks again later in gulp.task function. And it can list failed and undefined tasks with .fails and .undefs functions.

It's an independent module, so it can be removed easily when string name are obsoleted.

alvint commented 9 years ago

@heikki ECMAScript 6 modules looks quite interesting, and the Node side is the perfect place to be an early adapter. Any idea for the timetable on Node.js incorporating it? My guess is many in the Node camp are also in the "ECMAScript 6 is trying to turn JavaScript into Java" camp so support of it may be tepid for a while.

geekflyer commented 9 years ago

@heikki @alvint . Yeah ES6 module syntax looks nice, but would that have any impact on the forward referencing? I think the current commonjs module system is already very similar to ES6 modules.

phated commented 9 years ago

I just tried to implement this and I remembered why we can't do it:

The task listing methods we are adding that show the structure of your dependency tree would need to execute the tasks if we only built the tree at task runtime. By building the tree during gulpfile execution we have the entire tree without executing any tasks, which is the desired behavior if you are running gulp with --tasks flag. We are exposing all this information at the CLI because a lot of tools are adding gulp integrations and we want them to have as much information as possible (we are even exposing a --tasks-json flag for easy programmatic use). If we executed tasks to build the tree, it would be a very bad thing for these tools, imaging randomly having your dist cleaned on startup of your IDE.

phated commented 9 years ago

I want to keep string definitions (easy to support) but encourage named function usage (easier to compose)

alvint commented 9 years ago

@geekflyer No impact on forward referencing. Just shooting the breeze. :)

yocontra commented 9 years ago

@phated I don't think we need to run the tasks to build the tree...

phated commented 9 years ago

example

gulp.task('default', gulp.series('task1', 'task2'));
gulp.task('task2', gulp.series('task1'));
gulp.task('task1', fn);

if you wait until execution of a task before calculating the dependencies in gulp.series, you will never know that task2 relies on task1 without executing task2.

alvint commented 9 years ago

@phated Won't you have that issue regardless of whether you have forward references, and no matter how you figure out the task names (with labels or by using named functions)?

phated commented 9 years ago

@alvint no, the stuff we currently have works

alvint commented 9 years ago

Then from a CS/logic standpoint it must be doable with task names as well. You're just sticking additional functionality on top.

phated commented 9 years ago

I'm going to close this topic as it has already diverged multiple times. I am not going to be working on this feature and if someone wants to contribute actual code instead of bikeshedding it into oblivion and killing my will to work on gulp4, I will happily review the patch.

geekflyer commented 9 years ago

@phated What do you mean with "executing a task" ? Can't we simply implement a logic for gulp.task, gulp.series and gulp.parallel, so that the arguments (functions) are only executed for --task listing lookup when they are the output of gulp.series or gulp.parallel?

phated commented 9 years ago

@geekflyer i welcome you to read the gulp4 code to understand. feel free to submit a patch

geekflyer commented 9 years ago

Ok, I'll give it a try :-)

yocontra commented 9 years ago

I am not going to be working on this feature and if someone wants to contribute actual code instead of bikeshedding it into oblivion and killing my will to work on gulp4, I will happily review the patch.

@phated Please try to maintain an inclusive environment for people who want to contribute.

phated commented 9 years ago

@contra I believe I was being inclusive in saying that I am looking for help in this matter. I won't be implementing this as I don't see any way to do it that makes sense. More bikeshedding without code doesn't move the project along.

alvint commented 9 years ago

@phated didn't @sttk have code?

alvint commented 9 years ago

@phated In any case I'll write it. Just give me your requirements (what you wan't the interface and any API contracts to look like).

phated commented 9 years ago

All the code is there and you seem to be defining the requirements.

alvint commented 9 years ago

@phated You mentioned something about wanting to be able to list dependencies? How do you want that to work exactly?

phated commented 9 years ago

@alvint the gulp --tasks, gulp --tasks-simple and gulp --tasks-json commands all currently work as desired in the 4.0 branch. It needs to continue to work the same.

phated commented 9 years ago

Figured I would update this post. It was easiest to implement forward references as a custom registry - see https://github.com/undertakerjs/undertaker-forward-reference

mryellow commented 7 years ago

This makes migration to v4 much more time-consuming than it needs to be.

what's the point of a registry if everything needs to be defined in order?

I'm defining tasks here, with names as strings. I expect them to exist.

My fear with that approach is that users will see in G4 a product that is too different from the product they're already used to and like,

Upon discovering this, I'm ready to stick with v3 for the next 6 decades.

joeyhub commented 5 years ago

This might be a more significant problem in some cases than it appears. Sometimes tasks come from other systems and might consist of objects containing task name and function. Those aren't guaranteed to be in order in javascript.

This means having to do really weird things with the structure to get things to work.