A Better Makefile for Bootstrap


– 772 words

tl;dr Bootstrap's Makefile is not so good. So I'm starting to make it better.

A little bit of backstory:

My current side-project is learning how to play Bridge. To help learn about the bidding process, I am making a simple static site web app out of a coffeescript playing card library, BankersBox for client-side storage, and of course Bootstrap for layout and styling. The project is called bridge-trainer.

Since each component has a compile step, I decided to take a Jekyll-like approach by compiling the overall site into a _site directory which I then sync to S3 as a hosted bucket.

You can see the github repo, but the general setup is an html, js, and css folder with BankersBox, and Bootstrap living as git submodules underneath their respective directories.

When I'm ready to test a change, I background emacs with ^Z and type make to compile the site into a _site directory which I can load locally in my browser. You can see the first version of the Makefile which compiled the site.

The Makefile would create the _site directory, compile the coffeescript files, run the Bootstrap make file, then copy all the necessary files into the _site hierarchy.

Trouble was, Bootstrap would compile from scratch each time I ran make. This seemed rather unnecessary as none of the source files for Bootstrap were changing between site builds.

Here you can see near the top of Bootstrap's Makefile:

Original Makefile

Original Makefile

Bootstrap's Makefile is being used as a glorified shell script to run a bunch of commands and not using make's real power: a compilation asset dependency graph. Also, there is no all target, so if you just run a normal make command, the first target is run by default. In this case the first target is build which builds the docs for Bootstrap. This takes about 2.4 seconds each time.

$ time make build

##################################################
Building Bootstrap...
##################################################

Running JSHint on javascript...             Done
Compiling LESS with Recess...               Done
Compiling documentation...                  Done
Compiling and minifying javascript...       Done

##################################################
Bootstrap successfully built at 06:17PM.
##################################################

Thanks for using Bootstrap,
<3 @mdo and @fat

real    0m2.480s
user    0m2.299s
sys     0m0.170s

Run the same command immedately afterward, and you get the same thing.

$ time make build

##################################################
Building Bootstrap...
##################################################

Running JSHint on javascript...             Done
Compiling LESS with Recess...               Done
Compiling documentation...                  Done
Compiling and minifying javascript...       Done

##################################################
Bootstrap successfully built at 06:17PM.
##################################################

Thanks for using Bootstrap,
<3 @mdo and @fat

real    0m2.440s
user    0m2.271s
sys     0m0.172s

Another 2.4 seconds down the drain even though no input sources were changed.

At this point I decided I didn't want to wait 2.4 seconds each time I changed one line of html for my site and recompile to test it in my browser. At first I modified my project's Makefile to deal with Bootstrap's compilation dependencies as can be seen in this commit, but I thought it was a bit silly that I had to worry about that in my Makefile.

So, I did what any insane person would do. I forked Bootstrap.

Here is the updated Bootstrap Makefile using proper make target dependencies:

New Makefile

New Makefile

After running a make clean to start from scratch, running make bootstrap again takes 2.x seconds to compile.

$ time make bootstrap

real   0m2.711s
user   0m2.552s
sys    0m0.168s

But now if you run it again, nothing needs to happen because nothing changed! Voilà!

$ time make bootstrap
make: Nothing to be done for `bootstrap'.

real  0m0.032s
user  0m0.029s
sys   0m0.002s

This allowed me to have a much cleaner Makefile in my project's repo now that Bootstrap was worrying about itself.

Now if I cd back to my repo's root, compiling the site from a fresh start takes ~6 seconds while Bootstrap is compiled and BankersBox is minified by Google's closure compiler.

$ time make site

real   0m6.111s
user   0m2.567s
sys    0m0.236s

However, after I make an edit to one of the repo's files (like my playing card coffeescript) and recompile, it is lightning quick because all of the Bootstrap and BankersBox dependencies are already fulfilled.

$ touch js/coffee/cards.coffee
$ time make site

real   0m0.248s
user   0m0.217s
sys    0m0.030s

Mission accomplished. If I do decide to customize the look of the site by editing Bootstrap's .less files, my project's Makefile will automatically trigger a Bootstrap rebuild (but only the css files!) because of the build dependencies.

make can be a very powerful tool. It was designed to save developers' time by not repeating unnecessary compilation steps between builds of large programs. Use it wisely in your projects, and you just might save valuable seconds of your fellow developers' lives.

Further discussion on Hacker News.

— Fin.
Tagged: bootstrap make

Like this post? Please share the love!
blog comments powered by Disqus