2013/03/28
The main two contributing factors (after Adobe Flash) to the performance of mobile web pages are the number of request and the size of requests, as can be seen from the following data (source: http://mobile.httparchive.org/).
There are numerous techniques that can be used to reduce the number and size of requests. In this article I will talk about the general theory of this. In the next article I show a concrete example of minifying JS and CSS using WRO4J, the code for this can be found at https://github.com/jamesdbloom/base_spring_mvc_web_application.
Combine Requests - Bundling
To reduce the number of request the easiest first step is to combine static assets. This approach can easily be applied to CSS, JS or Images as follows:
> JavaScript / CSS Bundle - combine all files into a single bundle
> Image Sprite - combine all images into a CSS sprite, then display each part of the sprite inside a div. Set the background-image on the div which acts as a window onto the section of the sprite you need to display.
Combine Requests - Inlining
> Base64 Encoding - combine resources directly into HTML or CSS, use dataURI for external resources with Base64 encoding. Disadvantages are that resources can't be cached separately from HTML or CSS (therefore are reloaded every time) and Base64 encoded resources are 8/6 times larger.
> Aggressive Inlining - it is possible to reduce pages down to a single request. This initial request then stores inlined resources into localStorage so that any subsequent requests only loads the HTML. If localStorage or any other part of the solution does not work then for subsequent requests resources are loaded independently so that they are cached.
-
First Load:
- inline resources and set cookie
- put resources in localStorage and update cookie
-
Subsequent Load:
- 3. check cookie
- - if updated
- > load resources from localStorage (at top of page)
- - if initial value
- > no JavaScript or localStorage
- > return with resources as external links
Bing mobile uses this approach the 1st request is 54.9 KB then subsequent requests are 5.5 KB, i.e. 10x reduction.
Avoiding Requests
It is possible to use a number of other techniques to avoid some request all together.
- Avoid redirects - 71% of mobile sites have 3xx (302 / 301) redirects. If you can't avoid these at least add cache headers so they are cached.
- Replace image with CSS - use CSS to avoid images, such as, gradient, rounded corners, drop shadow, text shadow.
- Avoid animated GIFs - these are very expensive, replace them with a static image (from a sprite) and then rotate using JS.
Reducing Bytes
> Minify JavaScript / CSS - typically done during bundling using YUI Compressor or Google Closure Compiler. An online YUI Compressor is available as http://refresh-sf.com/yui. In the next article I show a concrete example of minifying JS and CSS using WRO4J, the code for this can be found at https://github.com/jamesdbloom/base_spring_mvc_web_application.
> Mini JavaScript Frameworks - don't send desktop JS to mobile use a mini framework such a XUI, Zepto, microJS, baseJS. Avoid heavy weight frameworks such as jQuery, Sencha, YUI, Dojo.
> Minify HTML - remove unnecessary whitespace and line breaks from HTML. If you are using a templating language such as FreeMarker use built in tags to remove whitespace and to compress HTML. For FreeMarker you can use and
> Adaptive Resources
- Adaptive Images - use media queries or UserAgent sniffing to load images of the correct size for the screen size. Images can be created at certain breakpoints and scaled dynamically (and cached) on the server between breakpoints.
- Adaptive JavaScript - use UserAgent sniffing to load device specific JavaScript target at specific browser. Frameworks like XUI provide different versions for each major type of browser.
- Adaptive CSS - use media queries to load only those styles that are relevant for the specific device, as below: