Eduard Malakhov
Eduard Malakhov

Reputation: 1114

Running gulp task on a module that has dependencies injected via gulp-submodule, that in turn have their own dependencies via gulp-submodule, fails

The title might sound a bit vague, but here's an example of what is going wrong. Suppose we have three modules ModuleA, ModuleB, and ModuleC, so that ModuleA depends on ModuleB and ModuleB depends on ModuleC. When we need to run a task against ModuleA, we oftentimes also need to run some tasks against its dependencies - ModuleB and ModuleC and here's where gulp-submodule comes into play. Gulp-submodule let's us define dependencies between tasks of a dependent module and its dependencies so that a task of the dependent module triggers appropriate tasks of its dependencies.

This works pretty fine if we have a flat structure, namely SomeModule depends on a bunch of other modules that have no dependencies of their own. However, once any of those dependencies has its own dependency, the whole ecosystem breaks with an obscure error message that tells that gulp fails to find a certain task.

Here's the demo code. To test this in a local environment, one must have at least gulp installed as a global package and both gulp and gulp-submodule installed as local packages for the project.

module-a.gulpfile.js

const gulp = require("gulp");
require("gulp-submodule")(gulp);

gulp.submodule("module-b", {filepath: "module-b.gulpfile.js"});

gulp.task("default", ["module-b:default"], () => {
    console.log("Running task 'default' for module 'module-a'...");
});

module-b.gulpfile.js

const gulp = require("gulp");
require("gulp-submodule")(gulp);

gulp.submodule("module-c", {filepath: "module-c.gulpfile.js"});

gulp.task("default", ["module-c:default"], () => {
    console.log("Running task 'default' for module 'module-b'...");
});

module-c.gulpfile.js

const gulp = require("gulp");

gulp.task("default", [], () => {
    console.log("Running task 'default' for module 'module-c'...");
});

Once you run task 'default' on module-a.gulpfile.js, you get an output similar to this:

gulp --gulpfile module-a.gulpfile.js
[07:15:27] Using gulpfile module-a.gulpfile.js
[07:15:27] Task 'module-b:module-c:default' is not in your gulpfile
[07:15:27] Please check the documentation for proper gulpfile formatting

As one might notice, gulp is looking for a certain task called 'module-b:module-c:default', although no task with such name is defined or referenced in any of the project files.

Upvotes: 2

Views: 598

Answers (1)

Eduard Malakhov
Eduard Malakhov

Reputation: 1114

This weird non-existing task comes from the way gulp-submodule handles dependencies between modules and tasks. In simple words, it does the following:

  1. First, at this call gulp.submodule("module-b", {filepath: "module-b.gulpfile.js"}) gulp-submodule temporarily replaces the original gulp.task and loads the specified gulpfile as a module.
  2. When the gulpfile is loaded, it gets the modified instance of gulp, where the task method modifies the name of the task submitted as its argument by prepending it with module name and a separator (":" by default).
  3. Later, when gulp runs task 'default' of module 'module-a', it comes across a dependency that we've referenced as "module-b:default", which is exactly the special name constructed for task 'default' of module 'module-b' in step 2.

With more than one level of dependency hierarchy, this straightforward logic breaks, because calling gulp.submodule("module-c", {filepath: "module-c.gulpfile.js"}) from module-b.gulpfile.js results in a gulp.task being wrapped by gulp-submodule the second time and hence the name of task 'default' for module 'module-c' gets prepended twice: first with 'module-c' and then with 'module-b'.

To fix this quickly, I've submitted a shortcut fix to our private of the original submodule: 5864ae5 (gulp-submodule). This is merely a quick fix and definitely not the best one, but it did the trick for me. I will update this answer, shall I come with a more solid solution to this issue.

Upvotes: 2

Related Questions