Construct Gulp Series Tasks Dynamically

Allen Fang
ShopBack Tech Blog
5 min readMay 8, 2018

--

In this topic, I want to share how to construct gulp@4 series or parallel task. It’s a common question if you want to write a high quality gulp tasks. But before that, I’m going to introduce basic concept for gulp.series and gulp.parallel.

gulp.series and gulp.parallel is almost same, but there’s a little different that is series execute the tasks one by one but parallel execute simultaneously. In the following demo, I will only use the series as the example.

gulp.series allow developer to register multiple tasks and execute them one by one, following is the explanation from official document:

gulp.series(…tasks)

Takes a number of task names or functions and returns a function of the composed tasks or functions.

When using task names, the task should already be registered.

When the returned function is executed, the tasks or functions will be executed in series, each waiting for the prior to finish. If an error occurs, execution will stop.

Ok, let’s see a simple example:

gulp.task('taskA', function(done) {
// omit...
done();
});

gulp.task('taskB', function(done) {
// omit...
done();
});
const demo = gulp.series('taskA', 'taskB');gulp.task('demo', demo);

gulp.series allow you to register task by an array or task name or function. In above example, we definitely declare taskA and taskB via gulp.task then register the both task to gulp.series then create a demo task for gulp.series. After that, you will see the below result by running command:

demo result

However, if you get a set of similar tasks but the amount is configurable or dynamical, how will you handle it? Let’s have a scenario to describe this question

Firstly, we have a project with following structure:

project
├── extension
│ ├── mainfest.json
│ ├── _locales/
│ └── images/

└── build

Let’s say, we want to release extension for five countries, following is our release tasks

  1. Clean and create the build folder
  2. Distribute extension folder by each country
  3. Patch manifest.json with different meta data per country
  4. Archive each one

Let’s illustrate above flow within a gulp mind:

The key question here is step three and four because after step two, we got different folders per country then we need to do something different patch on each manifest.json then archive them.

So right now, you can not write your task like below:

gulp.task('patch_USA_manifest', function(done) {
// omit...
done();
});
gulp.task('patch_Australla_manifest', function(done) {
// omit...
done();
});
// and so on

Actually, you can write your tasks like above example but it doesn’t make sense due to less maintainability and flexibility. If a new country added, developer need to figure out what tasks need to be modified.

Basically, we need a function which can generate task dynamically then register to gulp.series or gulp.parallel, let’s focus on the step 3(The case of patching manifest.json):

You can see the line:8, we map each country to each function, that is because gulp.series and gulp.parallel not only accept string task name but also a function!! So we are able to register these dynamical function to gulp.series like below:

Line:19

return gulp.series(...task);  // powered by ES6

But after running, you will see an error like:

Oh, probably I forget to call done callback, how about this in Line:19

gulp.series(...tasks);
done();

Actually, no error again but the tasks you registered to series will never run, because it’s totally wrong usage for gulp, above series task never get register.

Right now the problem is patchManifest is still another task in the other gulp.series, so you can not just return the gulp.series, you are supposed to call gulp.series in Line:19:

return gulp.series(...tasks)();

Actually, according to the document, gulp.series does return a function. However, I believe you will keep seeing the above error again, but this time, the patchManifest get running:

Five anonymous functions are executed successfully from line 10. It is expected, because we only have five countries. So the remain issue is we need to tell gulp we finish the patchManifest task:

return gulp.series(...tasks, () => done())();

Above, we define a final series task which will call done callback. After that you can get the correct result but you will see the same error after all tasks finish:

This is because we need to tell gulp we finish our final series task, so we need to change code again to finish the series task:

return gulp.series(...tasks, (seriesDone) => {
seriesDone();
done();
})();

Now, you never see any error and the output should be correct!! Following is our final code:

How to custom the dynamical function name

After experiencing all the cases and tackling above problems, you probably will see following output:

You can see there are so many anonymous functions, it maybe just a minor problem but it still can be improved by function.displayName:

Short explanation about done callback

You already see a lots of done callback be called in above example. Actually, done is used for signal a completion event and usually used in a callback style(Async operation). In the gulp@4, there are five solutions to handle the async tasks, done callback is just most simple one of them.

Conclusion

In this article, I just share a simple solution to construct gulp series/parallel tasks dynamically. However, you can still improve it more like a professional gulp guy via Stream or Promise, but I think it will be the other posts in the future. So Stay tuned!!

--

--