-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gulp.series() could be friendlier to run inside a function #2116
Comments
@gauntface hmmm. The general idea of these APIs is to compose functions at the top level. The pattern you showed is something that can be done due to the implementation but it's not a recommended pattern (thus looks bad). If we added your suggestion, I feel like many more people would be adding extra function wrappers into their programs (like I think most of these scenarios go away when people utilize flags and task metadata). (And named functions in the cases where they are dodging the forward reference changes) if (process.argv.includes('--prod')) {
process.env.NODE_ENV = 'production'
}
// "prod" no longer makes sense
export const generate = gulp.series(build, serviceWorker);
generate.flags = {
'--prod': "Set NODE_ENV to 'production'"
}; I understand you provided a pretty basic example and I'd like to see other samples to see how they could be converted to not add another function wrapper around |
The only other case I hit this is: https://github.com/google/web-starter-kit/blob/wsk-next/gulp-tasks/build.js#L20 I'm using gulp.parallel to manage when streams are done. The flag I live with as it results in a less verbose gulp config. |
I'm not sure I understand the level of indirection in that file (viewing from mobile).
I'm not sure I understand what's being stated here. |
Sorry - my brain is melting these days. Basically - using a flag is a good idea. The indirection of this file - I agree is weird. What I'm doing is that when a use runs I guess I'm fighting the use of a stream vs a promise. |
FYI feel free to close this bug as Won't Fix / Working as Intended if this is a use case that shouldn't be supported - I know I'm making abusing the current API's original intention. |
gulp.task('example', () => {
// Do stuff here
return gulp.series([....]);
}()); // <---- RIGHT HERE, the extra () Working Gulp 4 example: const gulp = require('gulp')
function foo(done) {
console.log('foo')
done()
}
exports.foo = foo
function bar(done) {
console.log('bar')
done()
}
exports.bar = bar
function baz() {
// ... do stuff ...
return gulp.series(bar, foo)
}
exports.baz = baz() where I could've also written the gulp.task('baz', () => {
// ... do stuff ...
return gulp.series(bar, foo)
}()) Does what you wanted. :) EDIT: It's important to note that in this case |
@trusktr your example is unnecessarily complex and doesn't do anything more than you could do outside the task definition. I'm assuming @gauntface wanted to defer the task evaluation until execution time in his example. |
@gauntface I was just looking over that task you sent us and I totally feel like that functionality best fits as a Custom Registry - I'd be happy to jump on a call if you want to dive deeper on those. |
@phated I'm trying to understand how that helps. Reading through the docs it seems like it's the underpinnings of Gulp, but it's extremely difficult to see how it relates to this issue and / or how it improves the approach linked to earlier on |
My interpretation of your logic is that you are trying to implement a "require-all" type of logic. Is that incorrect? That's exactly the functionality custom registries were designed for |
What I'm trying to do is have something along the lines of:
These tasks are largely useless on their own but would look for any files in a specific directory, in this case For example, The idea here is that it decouples the files implementing the chains from the overall build. Looking at the custom registries, I just ended up complicating the same code as I already have - so I could be using it wrong, but the docs just don't grok for me to see how I'd use them differently. |
Basically, any time you are warping the way gulp is used (as linked), it's probably much easier to implement a custom registry. e.g. I implemented forward references a couple lines using custom registries. If you look on the org, we have some reference impls. |
@gauntface I want to make sure there was a clear path forward. Did you get things worked out? |
Just tagging along for the ride here. I've something along the lines of the following:
I've used |
@nevercast the "gulp way" is to go plain js wherever possible, I would write your stuff as simply: const deploy = async () => {
log(`Starting deploy to ${configuration.serverName}`)
const deployer = createDeployerService()
await validateServer(configuration.serverName)
await deleteFilesFromServer(configuration.serverName)
await uploadDistToServer(configuration.serverName)
}
const deployTask = gulp.series(
loadConfiguration,
validateConfiguration,
buildWebpack,
jest,
karma,
deploy
)
export default deployTask You only need gulp.series/gulp.parallel when you start needing nesting, stream completion, callbacks, etc. - if you are using simple promises you can just use async/await normal JS stuff. |
@contra's answer here is really spot on! Sometimes those different APIs won't be promise returning and you can just nest series/parallel calls. // Notice how this doesn't need to be in a task?
// It could go inside the log task too, I suppose.
const deployer = createDeployerService();
const deployTask = gulp.series(
loadConfiguration,
validateConfiguration,
buildWebpack,
jest,
karma,
gulp.series(
async () => log(`Starting deploy to ${configuration.serverName}`),
validateServer(configuration.serverName),
deleteFilesFromServer(configuration.serverName),
uploadDistToServer(configuration.serverName)
)
);
export { deployTask as default }; |
I'm providing some more related feedback here. I'm working my way through upgrading a gulpfile to Gulp 4 that included about 30 or so tasks, a multi-day project. In a number of cases, it would have been very convenient to be able to The official API docs for series frankly aren't clear what it returns, they just say it's a composed operation. Well, what's that? Given all the async possibilities, maybe it's a promise under the hood and maybe it's not. The thing is that in a promise-based flow, promises are returned, and that's an increasingly expected pattern in modern async libraries. This may not been the case several years ago when the Gulp 4 effort was started, but that's the landscape today. If Here's an example of the gulp tasks I'm trying to update:
So, yeah, it would be really convenient if Promise were returned here. If that can't happen, the documentation could clarify things:
|
@markstos you're thinking about gulp composition completely wrong - perhaps you should review our brand-new Getting Started guide to help you start thinking in the currently recommended patterns. There's even mention of async/await patterns! |
@phated I checked out the link you provided and there is no mention that addresses the basic complexity of needing to compose a Since It's an unfortunate design choice in 2018 to have standardized all async tasks back into the ancient callback pattern. The workaround for developers who have more complex needs beyond the "hello world" examples is to bypass Multiple The value that |
@markstos Example gulpfile: export const someJob = async () => {
await doSomething()
await doSomething()
}
export const taskName = async () =>
Promise.all([
someJob(),
someJob()
]) |
There are a few scenarios where I've been wanting to write a task similar to:
This doesn't work because
gulp.series()
returns a function, and the execution of a task is expected to return a promise or a stream.So executing gulp.series, like so:
Running the
prod
task, it'll correctly run the series tasks, but at the end it'll print:In the end I need to write:
This works, but it would have been amazing if:
The text was updated successfully, but these errors were encountered: