Update on 2013-09-03: thanks to Xaero’s comment, I’ve added an example of Makefile minifying JavaScript files into a single one. Check at the end of the post.
If an iOS project contains some HTML/JS/CSS files in the package, it makes sense to minify/obfuscate them in the final .ipa file, which somewhat hinders the reverse engineering and probably decreases loading time. What follows in my solution to that point.
Suppose we have this src directory with the web application, and src/index.html is the main file. We could decide to minify them in the build products directory (somewhere /Users/user/Library/Developer/Xcode/DerivedData/appname-someletters/Build/Products/Debug-iphoneos/appname.app/), and that would isolate the converted files from the source. However, if you have over a few dozens of JS files, it quickly becomes expensive to run that process all over again with each build. Thus, we will go the other way.
Makefile
Since the make tool comes with OS X, a Makefile is a natural choice here, which won’t require any extra software. It will be integrated into the project’s build process. The Makefile creates a mirror hierarchy in src.min of that inside the src directory. It’s the first time I’ve written more or less complex Makefile, and so some decisions may not be optimal, but it works!
# This Makefile:# 1. [target: js] minimizes all .js files in src/ (except in lib/ and# legacy-related files) and stores them in a parallel hierarchy in src.min/# 2. [target: css] minimizes .css files in src/, as specified in index.html# (except legacy.css and commented lines), and compresses into one in src.min/css/## By default, the both targets are made.## http://www.egeek.me/# the directory with the source JS & CSS filesroot_dir= src
# the result dir suffix that is appended the root dir namemin_suffix= .min
# here we get all the .js files (except the exceptions) as a listJS_TARGETS=$(shell find $(root_dir) -type f -name '*.js' ! \( -path '*/lib/*' -or -path '*legacy*'\))# the same list, but the base directory is with the suffixJS_MIN_TARGETS=$(JS_TARGETS:$(root_dir)/%=$(root_dir)$(min_suffix)/%)# here we get the .css files (except the exceptions) from the index.html as a listCSS_TARGETS=$(shell sed -nE '/\.css/ { /(legacy\.css|<!--.*-->)/ { d; }; s/.*href="([^"]+)".*/$(root_dir)\/\1/; p; }'$(root_dir)/index.html)# the resulting one CSS fileCSS_MIN_TARGET=$(root_dir)$(min_suffix)/css/all.min.css
# set compressors and their optionsJS_COMP= java -jar ~/bin/js_compiler.jar
JS_COMP_FLAGS= --charset UTF-8 --jscomp_off internetExplorerChecks
CSS_COMP= java -jar ~/bin/yuicompressor.jar
CSS_COMP_FLAGS= --type css
# targetsdefault:jscss.PHONY:jscssjs:$(JS_MIN_TARGETS)# creates the directories for the output filedir_guard= @mkdir -p $(@D)# "It's a kind of magic"$(root_dir)$(min_suffix)/%.js:$(root_dir)/%.js$(dir_guard)$(JS_COMP)$(JS_COMP_FLAGS) --js_output_file $@ $<
css:$(CSS_MIN_TARGET)$(CSS_MIN_TARGET):$(CSS_TARGETS)$(dir_guard) @cat $^ |$(CSS_COMP)$(CSS_COMP_FLAGS) -v -o $@clean:$(RM) -rf $(root_dir)$(min_suffix)
It depends on the Java Runtime Environment, and two compressors: Closure Compiler for JavaScript, and YUI Compressor for CSS. Place them as ~/bin/jscompiler.jar and ~/bin/yuicompressor.jar respectively, or change the filenames in the file. The provided Makefile makes some specific exceptions for the project, and I left them in place in case you need something similar.
You should rename the file to Makefile after downloading. The file is commented, and if you have any further questions, leave a comment.
Xcode build
To run the make command on each build I’ve created a simple shell script and added it as a build step. Here’s the relevant part:
#!/bin/sh## http://www.egeek.me/function die (){echo$@exit1}cd"<where your Makefile is>"DSTDIR="${BUILT_PRODUCTS_DIR}/${EXECUTABLE_FOLDER_PATH}"[["$DSTDIR"==""]]&& die "Can't determine the destination directory for web files. Please check that the script is run within Xcode build process."echo"Checking the tools…"[ -r ~/bin/js_compiler.jar ]|| die "Warning! Closure Compiler is not available. Please install it here:" ~/bin/js_compiler.jar
[ -r ~/bin/yuicompressor.jar ]|| die "Warning! YUI Compressor is not available. Please install it here:" ~/bin/yuicompressor.jar
# this should minify & compress all js & css files into src.min/# get number of corescores=$(/usr/sbin/system_profiler -detailLevel full SPHardwareDataType | awk '/Total Number of Cores/ {print $5};')# … or 5cores=${cores:-5}echo"Compressing all js and css files…"# replace WARNING with note so that Xcode won't consider the warnings errorsmake -j${cores}2>&1| sed 's/WARNING/note:/'echo"Copying minified web resources to $DSTDIR…"cp -a src.min/{main,css,localization}"$DSTDIR"
NB! The original files (in src) are in the Xcode project, but not added to any target, because the script copies the minified versions itself.
Minifying js files into a single one
To minify the project’s js files into one, we pass all of them to Closure Compiler as arguments. Here’s a sample Makefile:
Here, in line 4, we find all *.js files in source directory, and use in the found, nondeterministic order. Most likely, there is an index.html file that includes the javascripts in some correct order. In that case, change line 4 to: