public
Last active

An example of using Make instead of Grunt for fast, simple and maintainable front-end asset compilation.

  • Download Gist
Makefile
Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
# A simple Makefile alternative to using Grunt for your static asset compilation
#
## Usage
#
# $ npm install
#
# And then you can run various commands:
#
# $ make # compile files that need compiling
# $ make clean all # remove target files and recompile from scratch
# $ make watch # watch the filesystem for changes and recompile
#
## Why?
#
# 1. Less dependencies
#
# Instead of needing a grunt-* wrapper library for your favourite tool, and
# needing to update or wait for a new version just to pass a new option into
# the underlying library, you can simply use the library directly.
#
# Thankfully all the awesome node libraries you're using with Grunt include
# command-line tools which are easily executable by make.
#
# 2. Easy to extend
#
# For this example we're using some linux commands for concating, and various
# node-based libraries for Sass compilation, CSS prefixing, etc.
#
# Adding a new tool or step to your asset compilation is dead simple:
#
# 1. add the library to package.json
# 2. npm install
# 3. add a new line to the revelant target, calling the binary created by npm
# install
#
# 3. Performance
#
# Makefile understands file modification times, so it won't recompile any
# targets whose source dependencies haven't changed. Combined with using a
# file modification monitoring tool like wach, you get near-instant recompiles
# of your front-end assets.
 
 
# Variables
 
APP=myapp
APP_JS_SOURCES=$(BOWER)/angular/angular.js $(JS)/$(APP).js
AUTOPREFIXER_BROWSERS="> 1%"
 
SASS=sass
JS=javascripts
 
BIN=node_modules/.bin
BOWER=bower_components
DIST=public
 
# Targets
#
# The format goes:
#
# target: list of dependencies
# commands to build target
#
# If something isn't re-compiling double-check the changed file is in the
# target's dependencies list.
 
# Phony targets - these are for when the target-side of a definition
# (such as "all" below) isn't a file but instead a just label. Declaring
# it as phony ensures that it always run, even if a file by the same name
# exists.
.PHONY : all clean watch
 
# Compile the final targets
all: $(DIST)/$(APP).css $(DIST)/$(APP).js
 
# Destroy the final targets
clean:
rm -f $(DIST)/$(APP).css $(DIST)/$(APP).js
 
# Watch the filesystem and recompile on file modification
watch:
$(BIN)/wach -o "$(JS)/**/*,$(SASS)/**/*" make all
 
# The final CSS file
$(DIST)/$(APP).css: $(SASS)/**
$(BIN)/node-sass $(SASS)/$(APP).scss $(DIST)/$(APP).css
$(BIN)/autoprefixer --browsers $(AUTOPREFIXER_BROWSERS) $(DIST)/$(APP).css
 
# The final JS file
$(DIST)/$(APP).js: $(APP_JS_SOURCES)
cat $(APP_JS_SOURCES) > $(DIST)/$(APP).js
Readme.md
Markdown

Give it a go:

git clone https://gist.github.com/6200029.git make-asset-compilation
cd make-asset-compilation
npm install
node_modules/.bin/bower install
mkdir -p javascripts sass public
echo 'console.log("Hello world");' > javascripts/myapp.js
echo 'html { background: papayawhip; }' > sass/myapp.scss
make

And then look in public to see your compiled files.

To watch it auto-recompile on file change, run make watch and then edit javascripts/myapp.js or sass/myapp.scss

bower.json
JSON
1 2 3 4 5 6
{
"name": "myapp",
"dependencies": {
"angular": "x"
}
}
package.json
JSON
1 2 3 4 5 6 7 8 9
{
"name": "myapp",
"devDependencies": {
"bower": "x",
"autoprefixer": "x",
"node-sass": "x",
"wach": "x"
}
}

Awesome use of Make! It's somewhat more difficult to configure, but the advantages are clear.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.