A recent article by Internet Retailer states that the Office Depot m-commerce website “exhibits spectacular performance”, citing our first-place ranking in Keynote Systems’ weekly rankings, in which the Office Depot mobile website achieved a perfect score of 1000. There are two main components in this performance rating: uptime and page load speed. The uptime is the result of our mobile website being served by the same servers that handle our main website, where load balancing, performance tuning and redundancy have been in place for years. The page speed is the result of careful planning in the presentation layer.
The first decision I made was to eschew frameworks that created an app-like experience, such as Sencha Touch or jQuery Mobile. Because we use jQuery with great success on our websites, it was assumed that we would use jQuery Mobile on our mobile website. Although jQuery Mobile is a terrific framework, there is additional overhead involved in mimicking the native app experience. But since we already had a native app for both Android and iPhone we did not need to compete with it. (I would have considered a framework for our European mobile website, which did not have a native app version, and which did have to compete in the mobile app space with other merchants.)
Our primary directive in building the mobile website was “make it fast”. Fast means light, and jQuery Mobile requires jQuery to work. That’s two frameworks. Even gzipped and minified they weigh in at 56k, not counting the CSS theme. Instead I chose XUI at 4.2k. XUI is described by its authors as “a super micro tiny dom library for authoring html5 mobile web applications”. Although 56k for jQuery doesn’t sound like much, performance testing by Google shows that parsing 1k of Javascript takes about 1ms. And parsing doesn’t just happen once, but on every page.
We could have written everything in native Javascript, but XUI gave us the basics, such as selection by class and XHR, and did so more efficiently than we could have done. Using XUI with native Javascript gave us the best of both worlds and probably ended up creating less code than if we hadn’t used XUI. It’s familiar jQuery-like syntax meant practically no learning curve for our team.
Another crucial decision was to inline both the Javascript and the CSS. This is anathema in normal front-end development, but for mobile development it makes sense. Because all HTTP requests have to pass through the cell carrier before reaching the server, it takes longer to complete each request. Also, mobile browser HTTP request headers are, on average, 30% larger than for desktop browsers, causing another performance hit. So particularly on the home page we sought to make as few requests as possible.
Inlining the CSS enabled me to sprite both the inline and the CSS images—in the same sprite! Normally we serve CSS and inline from two different CDNs because they are referenced from two distinctly different paths. (CSS images come from within our web project and are part of the build. Inline images come from a separate server that is accessible by the business.) However since the CSS was in a jsp page I wrote the CSS image names as Java variables, which were inserted into our CSS at compile time in much the same way as LESS or SASS would have done it.
This innovative technique of using the same sprite for an inline image as for a CSS image worked very well for us. I sprited our logo and all of our icons and arrows on a single sprite. To put them inline, I made a clipping box with CSS and used negative margin to position the sprite. It worked beautifully across all the devices we tested. I did CSS spriting for the icons and arrows in the traditional way. I also used CSS3 to create graphics whenever possible.
Many mobile performance experts recommend using data URIs for images, but we decided not to do this. We had very few graphics, they were sprited and the sprite included our logo. We did not want to take even a small chance that our logo wouldn’t show up if a device didn’t understand the data URI. Data URIs still take a lot of bytes to express a file, so the real advantage is saving a resource request. Since we were requesting only 3 images for the home page, we felt we would not get a benefit from data URIs.
Despite our big performance win, we still have work to do. We did not get local storage implemented in the first iteration of the site, which would not have helped us on the home page, but would have made subsequent pages a bit speedier. The sprites evolved as the business changed their mind about aspects of the design. With the final graphics in place the sprite could be re-optimized for a slight improvement. But the biggest challenge is to keep up the “less is more” philosophy and not go overboard with ads and extras as the site evolves. Top performance is a constant challenge!