React and be thankful A blog about building (reactive) web applications

Building with Gulp: Caveats

After extolling Gulp's capabilities and highlighting how much it is an improvement from Grunt, it is only fair to discuss Gulp's limitations. Remember, in the fast evolving world of software development, tools are created to overcome limitations from their predecessors as well as trying to be as much future-proof as possible. It would be presumptuous to think that Gulp is a silver bullet (nothing is) and Gulp has also its own limitations and caveats, edge cases were its architecture is not so suitable.

Error management in Gulp 3

In Gulp 3, error management is an issue. In Gulp 3 it is unclear what strategy needs to be adopted when a piece of pipeline or a task fails. This is most problematic when using .watch() and in most cases developers are forced to re-start the build process manually either because the process exited, or because watching got messed up. Watch can stop working as expected because by design, when an event error is raised, a Node stream stops accepting data coming in. gulp-plumber is a monkey-patch preventing Node stream's default behavious on error (it prevents streams to unpipe on error).

However, this is not the only case where error management is not efficient. With linters, errors are raised when encountered and all linting errors are not all logged at once. If we use a jshint + uglify combination, ideally jshint would log all errors encountered but wouldn't write downstream so uglify itself wouldn't raise an exception if the AST cannot be parsed.

Gulp's team told its community error management is a priority in Gulp 4.

MANY:1 disguised as a 1:1

In Part 4: incremental builds, I deliberately eclipsed one case which makes Gulp suck at incremental builds: I call those cases the MANY:1 disguised as a 1:1. Those are the cases where a plugin will receive one file, but will end up processing many for finally passing downstream one file. Examples of this include: LESS, SASS or Browserify. LESS and SASS will need to follow @import files and read them from disk, and Browserify will track down module dependencies on your file system. Streams are bypassed and consequently incremental builds are not always possible.


Gulp is an amazing tool, don't get me wrong, and its syntax is awesome. Using .pipe() to create a transformation pipeline on a group of files is very nice and Gulp is a massive step forward from Grunt. But I don't think Gulp is the ultimate build tool of today (it doesn't mean it cannot become the ultimate build tool of tomorrow). Why is that? Simply because Gulp is NOT a build tool out of the box: you still have after having defined your tasks to tell Gulp how to clean, how to build, how to watch and how to increment.

Something wrong? Fix it on Github!