Building with Gulp.js
Getting started was easy, with npm and Bower downloading and installing the dependencies I needed; it all felt very familiar to Maven, Gradle and Leiningen I'm used to from back-end dev. But there's one part missing: Bower pulls the libraries, but doesn't provide them to my app. I have to maintain my dependency list in my build file as well, to ensure the libraries are linked in my index.html in the right order.
"That's not very DRY", I thought, "I should automate this".
I took a look around and couldn't find an existing tool to do it, so I put it together myself. Here's how to do it.
Dependency management with wiredep and gulp-inject
Bower knows about transitive dependencies, but doesn't expose that information in a way that can be easily consumed in
bower.json files of each
dependency in order. This job is done for us by wiredep. Its gulp plugin
isn't very configurable, but that's ok, because we don't need gulp plugins. Wiredep itself
can produce a list of our dependencies and wire it into our
index.html. Wiredep won't do the same for our own code
though, for that we'll use gulp-inject.
First, we add placeholders for our CSS links and script tags to our
index.html, which is where wiredep
(using bower:blah) and gulp-inject (using inject:blah) will write in our tags:
In the spirit of automating ALL THE THINGS, in our gulpfile let's use the gulp-load-plugins plugin:
That exposes all the plugins we have in our
package.json inside the plugins variable, and we don't have to worry about
adding each one manually. As we aren't using the wiredep plugin, we still require it directly.
Wiredep calculates the dependency list and stores it in its
css variables; we can use these in our gulp
tasks to copy the files to the
Now we process the
index.html to reference all these files. We pipe it through wiredep and gulp-inject, and write it
out at the end:
There are two main things going on here: wiredep's injection of third party dependencies, and gulp-inject's, um,
injection of our own dependencies into the
We're using wiredep's
stream() function, so we can use it as part of a
node stream; it reads our project's
bower.json, calculates the
dependency tree, generates the
<link> tags for all our dependencies, in the correct order, and injects
them into the
index.html. The configuration here is telling it that the tags it creates should be pointing into the
vendor directory, where we've stuck all our third party libraries in the
vendor-css gulp tasks
We also want to inject our own script files after all the dependencies, but wiredep doesn't stretch that far, so we add
a bit of work for gulp-inject to do: we simply give it a glob that picks up our code in the output folder, and
transforms the paths so they're relative to the build
index.html instead of the source one. Much like we did with
wiredep, we tell it how to generate the
<link> tags in the right way.
It's nearly there! Every time I add a dependency to my
bower.json, it'll automatically get wired into my
index.html, so long as the main entry in its
bower.json is correct. Sadly quite a few libraries don't provide this
information. In these cases, you need to add an override to your
bower.json for the problematic library: