Create a gist now

Instantly share code, notes, and snippets.

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

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

{
"name": "myapp",
"dependencies": {
"angular": "x"
}
}
# 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
{
"name": "myapp",
"devDependencies": {
"bower": "x",
"autoprefixer": "x",
"node-sass": "x",
"wach": "x"
}
}
@mstrcnvs

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

@sshelagh

I think you have a typo in your example makefile. On line 82 you have
$(BIN)/wach -o "$(JS)//*,$(SASS)//*" make all
where wach should be watch.

@sshelagh

but I should also say thank you for the gist.

@STRML
STRML commented Jul 7, 2014

@sshelagh It actually is wach.

@QuantumInformation

great, I'm tired of re-learning js build tools

@SerkanSipahi

instead using of $(BIN)/node-sass or a other service you can declare top of your makefile:

export PATH := $(PATH):$(PWD)/node_modules/.bin

then you have you write just node-sass, autoprefixer, etc. :)

@marlun
marlun commented Feb 28, 2015

Note that adding node_modules/.bin after your default PATH will run globally installed tools instead of the locally installed ones if they are installed in both places.

@daiyi
daiyi commented Feb 17, 2017 edited

Make automatically watches files for changes! You can run watch make all to use unix watch to run make every 2 seconds and it will recompile on modification and you won't have to install wach :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment