Minify javascript with GNU Make
June 9, 2017
In my former blog post I wrote an introduction how to set up Makefile to generate CSS and minify CSS from Sass files. In this blog post I will extend the Makefile with a rule for generating minified javascript files.
My folder structure and Makefile looks like this:
FOO-project/
static/
css/
/* here comes the generated css files */
js/
base.src.js
/* the minified js files will also be placed in this directory */
scss/
base.scss
login.scss
shop.scss
_variables.scss
_mixins.scss
CSS_OBJ = static/css
SASS_SRCS = scss
CSS_DEPS = $(wildcard $(SASS_SRCS)/_*.scss)
CSS_SRCS = $(filter-out _%, $(notdir $(wildcard $(SASS_SRCS)/*.scss)))
CSS_OBJS = $(patsubst %.scss, $(CSS_OBJ)/%.src.css, $(CSS_SRCS))
CSS_MIN_OBJS = $(patsubst %.scss, $(CSS_OBJ)/%.min.css, $(CSS_SRCS))
all: $(CSS_OBJS) $(CSS_MIN_OBJS)
$(CSS_OBJ)/%.src.css: $(SASS_SRCS)/%.scss $(CSS_DEPS)
scss $< $@
$(CSS_OBJ)/%.min.css: $(SASS_SRCS)/%.scss $(CSS_DEPS)
scss --sourcemap=none --style compressed $< $@
clean:
rm -f $(CSS_OBJS) $(CSS_MIN_OBJS)
.PHONY: clean all
.SUFFIXES: # Delete the default suffixes
.SUFFIXES: .min.css .src.css
UglifyJS
You need a package which minifies the javascript files. I use UglifyJS for this task, it is a javascript parser, compressor and beautifier. You can install it via npm:
$ npm install -g uglify-js
I create a variable called JS_MIN_OBJS, which replaces the .src.js file name with .min.js file name from the source files 'static/js/*.src.js'. I put this line below the variable CSS_MIN_OBJS in the Makefile:
CSS_MIN_OBJS = $(patsubst %.scss, $(CSS_OBJ)/%.min.css, $(CSS_SRCS))
JS_MIN_OBJS= $(patsubst %.src.js, %.min.js, $(wildcard $(JS_SRCS)/*.src.js))
Now I add the UglifyJS rule in the Makefile with the UglifyJS options for generating the wanted minified output. I put this line of code below the rule for minifying css:
$(CSS_OBJ)/%.min.css: $(SASS_SRCS)/%.scss $(CSS_DEPS)
scss --sourcemap=none --style compressed $< $@
%.min.js: %.src.js
uglifyjs --comments -c hoist_vars=true,join_vars=true -m -r '$$' -o $@ $<
The UglifyJS options are documented on their github page, another resource is a blog post from David Walsh. You can also find the list of options in your terminal with the command: *uglifyjs -h*.
In my example I ask uglify to preserve the copyright comments in the output *(- -comments)* and compress *(-c)* the file with the following options:
- *hoist_vars=true*: Move all variable declarations to the top of the file.
- *join_vars=true*: Join the var declarations.
- *-m*: Mangle names, this reduces the names to single-letter.
- *-r '$$'*: Exclude $ from the mangler.
- *-o $@ $<*: Output to min.js ($@) from .src.js ($<).
To let Make also run the uglify task, I need to add $(JS_MIN_OBJS) to the all target. I also want that the minified files are deleted when running make:
CSS_OBJ = static/css
SASS_SRCS = scss
JS_SRCS = static/js
CSS_DEPS = $(wildcard $(SASS_SRCS)/_*.scss)
CSS_SRCS = $(filter-out _%, $(notdir $(wildcard $(SASS_SRCS)/*.scss)))
CSS_OBJS = $(patsubst %.scss, $(CSS_OBJ)/%.src.css, $(CSS_SRCS))
CSS_MIN_OBJS = $(patsubst %.scss, $(CSS_OBJ)/%.min.css, $(CSS_SRCS))
CSS_MAPS = $(patsubst %.src.css, %.src.css.map, $(CSS_OBJS))
JS_MIN_OBJS= $(patsubst %.src.js, %.min.js, $(wildcard $(JS_SRCS)/*.src.js))
all: $(CSS_OBJS) $(CSS_MIN_OBJS) $(JS_MIN_OBJS)
$(CSS_OBJ)/%.src.css: $(SASS_SRCS)/%.scss $(CSS_DEPS)
scss $< $@
$(CSS_OBJ)/%.min.css: $(SASS_SRCS)/%.scss $(CSS_DEPS)
scss --sourcemap=none --style compressed $< $@
%.min.js: %.src.js
uglifyjs --comments -c hoist_vars=true,join_vars=true -m -r '$$' -o $@ $<
clean:
rm -f $(CSS_OBJS) $(CSS_MIN_OBJS) $(CSS_MAPS) $(JS_MIN_OBJS)
.PHONY: clean all
.SUFFIXES: # Delete the default suffixes
.SUFFIXES: .min.css .src.css .min.js
Run make in the terminal and the minified files are generated. In the terminal you'll get the following output:
$ make
uglifyjs --comments -c hoist_vars=true,join_vars=true -m -r '$' -o static/js/base.min.js static/js/base.src.js
That's it. You only need 4 lines of code to minify your javascript files. Together with compiling CSS and minifying CSS it is only 30 lines of code. That's pretty clean.