Last Updated: February 25, 2016
·
1.127K
· jdp

Web devs can use Make too!

It's now pretty common in web development to compile source files before deploying them, and there are many language-specific custom solutions to do that. In a lot of cases these tools can be overkill, when a simple Makefile would accomplish the task handily. Make is installed on pretty much every system by default, and being familiar with it is a great boon to any generalist developer.

So how can we use it in the context of web development? Well, you do precompile your Handlebars templates right? Say you were building a little Twitter client with Handlebars, and you're ready to make a deployment. You've got your three handlebars templates, but you want to compile them to templates.js in your scripts directory. Here's a Makefile that would accomplish that:

TEMPLATESRC = templates/profile.handlebars templates/timeline.handlebars templates/tweet.handlebars
TEMPLATEOBJ = ${TEMPLATESRC:.handlebars=.js}
TEMPLATEOUT = js/templates.js

$(TEMPLATEOUT) : $(TEMPLATEOBJ)
    cat $^ > $@

%.js : %.handlebars
    handlebars $< -f $@

.PHONY : templates
templates: $(TEMPLATEOUT)

Now just run make templates and your templates are built. The syntax looks pretty arcane, but here's a the gist of how it works. The TEMPLATESRC variable is just a list of the input template files. The TEMPLATEOBJ variable is a transformation over the input list, replacing the .handlebars suffix with the .js suffix. The TEMPLATEOUT variable is just the name of the compiled JavaScript template file.

The rest of the Makefile is the dependency specification. Really a Makefile is just a list of targets and their dependencies, and the steps for resolving the dependencies. Targets and dependencies are declared by with the TARGET : DEPENDENCIES syntax. So $(TEMPLATEOUT) is a target that depends on $(TEMPLATEOBJ), which is basically saying that for us to build templates.js, we must first build profile.js, timeline.js, and tweet.js. The rules for building the individual .js files for each template is handled by the %.js : %.handlebars rule, which specifies how to make a .js file from a corresponding .handlebars file. In that rule the we use two of Make's implicit variables: $< is the name of the first dependency and $@ is the name of the target. They're used to run the handlebars command to compile the individual template. Once the individual templates are compiled, the $(TEMPLATEOBJ) dependency of $(TEMPLATEOUT) is satisfied. The final templates.js file is built by concatenating all the individual .js files (specified by $^ implicit variable, which contains every dependency) into the target file, again specified by $@.

Even if you don't use Make in your own projects, it's good to be familiar with anyway. Being able to navigate and modify them in other projects is a handy skill, and it also gives you a chance to play around in a declarative programming environment.