When I was first starting my career as a Web Developer in the nineties, we were all about saving bandwidth. We compressed images, removed newline characters, whatever we could do to decrease the size of our downloads. As the World Wide Web grew to what it is today, bandwith increased, browsers became more efficient in caching and DNS prefetching and people slowly shifted their attention to making their sites dazzle and compete for audience attention rather than optimizing download speeds. Now, the pendulum is starting to swing in the opposite direction because, for one thing, people’s attention span has shortened and you just can’t get away with making them wait. Furthermore, as sites become increasingly interactive, their use of client-side script libraries has increased exponentially. All this leads one to the realization that we must optimize our sites.
Thanks to Paul Irish’s HTML5 Boilerplate Build tool, we don’t have to go through a lot of trouble to do it. In fact, Mr. Irish would have us believe that it can be as easy as clicking a batch file! To put this bold claim to the test, I ran the build tool against my robgravelle.com index page, along with its associated script, CSS, and image files. I’m happy to report that it really is quite easy to get the hang of.
How it Works
The build tool is really a collection of separate utilities bound together by an Apache Ant script, which is a popular Java-based build tool. Being Java-based makes it platform independent, making it easy to move from one environment to another. Some of the tools that it uses include jpegtran and optipng, for compressing JPEG and PNG images respectively. This step alone can save 50 percent of loading speed! It also revises file names, using REVed, so that you can employ heavy caching, while still updating assets when a new build is rolled out. Html minification, performed via htmlcompressor, can be set to from basic to aggressive using property files.
Before you Run the Build Tool
There are a few things that you’ll have to do before you call the build script. The first is to make sure you’ve installed both the Java runtime-environment (JRE) and Ant, in that order. On Windows, you should install Ant using WinAnt. It will run a Wizard to guide you through the installation process, making it super-easy!
The next step is to configure the property files.
The build tool expects the directory to mimic that of the HTML5 Boilerplate Template, which is:
index.html js -- - | libs - contains common script libraries such as Modernizr and jQuery mylibs - contains site specific custom library scripts plugins.js - contains all jQuery plugins scripts.js - contains site/page specific JavaScript code css -- | style.css handheld.css img (erroneously reported as images in build tool docs!)
Chances are that if you did not use the HTML5 Boilerplate Template to build your site, it won’t conform to these exact specifications, so you’ll have to set some values in the properties files.
There are two property files located in the buildconfig folder called default.properties and project.properties. The default.properties are the “goto” properties, while the project.properties override the defaults for project-specific attributes.
Perhaps the most important one is the dir.source. It’s where your project resides. By default the build script expects your project’s root to be in the same directory as the build folder. Unless you update this value, you should move or copy your build folder to the root of your project, where the index.html file resides.
Directory Paths
The Directory Paths section is where you would set the names and location of various folders. Here are the values with extra comments explaining what each property is for:
# # Directory Paths # dir.source = . #project root is where ever the build folder is located by default dir.intermediate = intermediate #this is a kind of temp folder. It's not needed to publish #so you may want to have it outside of your project tree structure dir.publish = publish #this is the folder that will contain your prod-ready site with optimizations dir.build = build # the build tool root folder dir.build.tools = ${dir.build}/tools #tools used by the build script dir.test = test #a project folder containing test files dir.demo = demo #a project folder containing demo files dir.js = js #the root JavaScript folder dir.js.main = ${dir.js} #folder containing your main JS file # scripts in the libs directory will only be minified, not concatenated together dir.js.libs = ${dir.js}/libs #a folder containing common script libraries such as Modernizr and jQuery dir.js.mylibs = ${dir.js}/mylibs #a folder containing site specific custom library scripts dir.css = css #the css folder dir.images = img #the image folder
In the project.properties, assign your Html page(s) to the file.pages property unless you only have one page named index.htm.
# Files can be added in a comma separated form file.pages = RobGravelle.htm
Excluding Files
In addition to files in the default.properties file, like .project and README files, you can designate additional files for exclusion using the file.exclude property. The mylibs directory has a separate property for JavaScript files called file.js.bypass.
Running the Build Tool
All you have to do to run the Build Tool is navigate to the build folder and call Ant. Here’s the output of a successful run:
E:unprotectedCIC PC BackupwritingsArticlesITHTML GoodiesHTML5-boilerplate HTML5 Boilerplate BuildTest Projectbuild>"C:Program FilesWinAntbinant" Buildfile: E:unprotectedCIC PC BackupwritingsArticlesITHTML GoodiesHTML5- boilerplateHTML5 Boilerplate BuildTest Projectbuildbuild.xml build: [echo] Building a Production Environment… -rev: [echo] ===================================================================== [echo] Welcome to the HTML5 Boilerplate Build Script! [echo] [echo] We're going to get your site all ship-shape and ready for prime time. [echo] [echo] This should take somewhere between 15 seconds and a few minutes, [echo] mostly depending on how many images we're going to compress. [echo] [echo] Feel free to come back or stay here and follow along. [echo] ===================================================================== [echo] [echo] -mkdirs: [echo] Creating directory structure… publish [copy] Copied 1 empty directory to 1 empty directory under E:unprotectedC IC PC BackupwritingsArticlesITHTML GoodiesHTML5-boilerplateHTML5 Boilerpla te BuildTest Projectintermediate [mkdir] Created dir: E:unprotectedCIC PC BackupwritingsArticlesITHTML GoodiesHTML5-boilerplateHTML5 Boilerplate BuildTest Projectpublish [copy] Copied 11 empty directories to 11 empty directories under E:unprote ctedCIC PC BackupwritingsArticlesITHTML GoodiesHTML5-boilerplateHTML5 Boi lerplate BuildTest Projectpublish -js.all.minify: [echo] Minifying scripts [copy] Copying 3 files to E:unprotectedCIC PC BackupwritingsArticlesIT HTML GoodiesHTML5-boilerplateHTML5 Boilerplate BuildTest Projectpublish -js.main.concat: [echo] Concatenating Main JS scripts… -js.mylibs.concat: [echo] Concatenating JS libraries -js.scripts.concat: [echo] Concatenating library file with main script file [copy] Copying 1 file to E:unprotectedCIC PC BackupwritingsArticlesIT HTML GoodiesHTML5-boilerplateHTML5 Boilerplate BuildTest Projectpublishjs -css: [echo] Concatenating any @imports… [copy] Copying 1 file to E:unprotectedCIC PC BackupwritingsArticlesIT HTML GoodiesHTML5-boilerplateHTML5 Boilerplate BuildTest Projectintermediate css [echo] Minifying css… [apply] Warning: style-concat.css modified in the future. [copy] Copying 1 file to E:unprotectedCIC PC BackupwritingsArticlesIT HTML GoodiesHTML5-boilerplateHTML5 Boilerplate BuildTest Projectpublishcss [echo] Minifying any unconcatenated css files… -usemin: [echo] Switching to minified js files… [echo] Kill off those versioning flags: ?v=2 [echo] Remove favicon.ico reference if it is pointing to the root [echo] Update the HTML to reference our concatenated script file: js/27f8b5 e6f9013c675db385588386d0175c8a8148.js [echo] Updating the HTML with the new css filename: css/471e69f144b6b34b032 e23c2879b78eadea4ae59.css -manifest: [echo] no manifest.appcache generated! -htmlclean: [echo] Run htmlcompressor on the HTML [echo] - maintaining whitespace [echo] - removing html comments [echo] - compressing inline style/script tag contents -imagespng: [echo] Optimizing images… [echo] This part might take a while. But everything else is already done. [echo] [echo] First, we run optipng on the .png files… -imagesjpg: [echo] Now, we clean up those jpgs… -copy: [echo] Copying over new files… [copy] Copying 27 files to E:unprotectedCIC PC BackupwritingsArticlesI THTML GoodiesHTML5-boilerplateHTML5 Boilerplate BuildTest Projectpublish [echo] A copy of all non-dev files are now in: ./publish. -build.production: BUILD SUCCESSFUL Total time: 16 seconds
Assessing the Results
Starting with the HTML page, we can see that the IE conditional statements have been condensed somewhat by the removal of extra newlines and spaces:
Before:
After:
Same for inline styles:
Before:
After:
The effect on scripts is especially dramatic.
Before:
After:
External stylesheets were minified by removing spaces and newlines and by including @import statements. Here are the first few lines of the main.css file:
Before:
/* body.forms div#content { position: relative; } */ /********************************* * SECTION 1: General Properties * **********************************/ /* * General html and body properties. */ html { } body { margin: 0px; padding: 0px; font-family: Arial, Helvetica, Verdana, sans-serif; font-size: 90%; }
After:
@import url(teasers.css);body{margin:0;padding:0;font-family:Arial,Helvetica,Verdana,sans-serif;font-size:90%}
Linked JavaScript files were similarly minified. Here are the first few lines of the Lightbox.js file:
Before:
var resizeSpeed = 8; /* 1 = slowest, 10 = fastest */ var borderSize = 10; /* Update this f you adjust the padding in the CSS */ /* Globals */ var imageGroups = new Array; var imageArray; var activeImage; if (resizeSpeed > 10) { resizeSpeed = 10; } if ( resizeSpeed < 1 ) { resizeSpeed = 1; } var resizeDuration = (11 - resizeSpeed) * 0.15;
After:
var resizeSpeed=8;var borderSize=10;var imageGroups=new Array;var imageArray;var activeImage;if(resizeSpeed>10){resizeSpeed=10}if(resizeSpeed
Scripts in the jsmylibs folder were amalgamated into one minified script called “27f8b5e6f9013c675db385588386d0175c8a8148.js” and placed in the js root:
Conclusion
Nothing could be done for my image files because my host’s Content Management System already incorporates image optimization. Nonetheless, I did achieve a overall site reduction of sixteen percent, from 456 KB (467,122 bytes) or 1.62 MB (1,703,936 bytes) on disk, to 381 KB (391,058 bytes) or 1.46 MB (1,540,096 bytes) on disk. That’s still substantial enough to make the build process worth while.