#SAM2013 Ribbon
15 things you can (and should) do to make your site faster for mobile users
Posted in: Speed Up Tips   -   August 29, 2012

I thought this seemed like a timely post given Keynote’s new report showing that 64% of smartphone users expect sites to load in 4 seconds or less. This finding isn’t a total surprise. Previous studies have shown that people expect sites to load at least as fast on their mobile devices as they do on their desktops. But it’s still a wake-up call for any site owner who may have lapsed into a bit of complacency. (And given the fact that it’s August, we’re probably all a little guilty of lapsing into late-summer complacency.)

As you may already know, about 80% of the time it takes to display a typical web page is shared between performing client-side processing and loading resources like stylesheets, script files, and images. So the three main strategies for improving performance — for both mobile and desktop visitors — are to:

  1. Reduce the number of HTTP requests required to fetch the resources for each page.
  2. Reduce the size of the payload needed to fulfill each request.
  3. Optimize client-side processing priorities and script execution efficiency.

As you probably also know, mobile users face unique performance challenges when it comes to implementing the strategies above. These challenges include:

  • Slower networks (which is why reducing requests and payload is important)
  • Mobile browsers are slower to parse HTML and slower to execute JavaScript (so optimizing client-side processing is crucial)
  • Mobile browser caches are much smaller than those of desktop browsers (requiring new approaches to leveraging local storage of reusable resources)

There are a number of fundamental and advanced tactics that you can use to take on these challenges and win. I’m going to give an overview of each one here, but to get more insight and specific how-to details, I urge you to download Strangeloop’s whitepaper on mobile website optimization.

REDUCE REQUESTS

1. Consolidate resources

By now, this is a standard practice, so I’m not going to explain it here, but I want to point out that resource consolidation can be a double-edged sword for mobile browsers. Reducing requests speeds up page load the first time, but larger consolidated resources may not be cached efficiently. So if you’re using this technique, make sure to balance it with techniques to optimize local storage (coming up next).

2. Use browser caching and localStorage

Caching is an essential technique for achieving acceptable performance, but desktop and mobile caches are not created equal. Mobile browser caches are usually much smaller than on desktop machines, causing items to be flushed quickly, so traditional browser caching doesn’t work well for mobile devices. Luckily, the HTML5 Web Storage specification, which has been implemented in all major desktop and mobile browsers, provides a great alternative to relying solely on browser caching.

3. Embed resources in HTML for first-time use

If a resource doesn’t have a high likelihood of already being cached (such as in a mobile context), it is often best to embed that resource in the page’s HTML — a technique called “inlining” — rather than storing it externally and linking to it.

The disadvantage of inlining is that page size can become very large, so it’s crucial for a web application that uses this strategy to be able to track when the resource is needed and when it is already cached on the client. In addition, the application must generate code to store the resource on the client after sending it inline the first time. For this reason, using HTML5 localStorage on mobile devices (as described above) is a great companion to inlining.

4. Use HTML5 server-sent events

The HTML5 EventSource object and Server-Sent events enable JavaScript code in the browser to open a much more efficient channel from the server to the browser, which the server can then use to send data as it becomes available, eliminating the HTTP overhead of creating multiple polling requests.

5. Eliminate redirects

When users try to navigate to a standard desktop site from a mobile device, this often generates an extra round trip to the client and back to the mobile site, consuming several hundred milliseconds over mobile networks. For obvious reasons, it’s faster to deliver the mobile web page directly in response to the original request, rather than delivering a redirect message that then requests the mobile page. And as a courtesy to users who prefer to view the desktop site on their mobile device, you can provide a link on the mobile site that signals your application to suppress this behavior.

REDUCE PAYLOADS

6. Compression and minification

Compression and minification are core best practices. Compression technologies such as gzip reduce payloads; text-based responses, including HTML, XML, JSON, JavaScript, and CSS, can all be reduced in size by as much as 70%. Minification, which is usually applied only to scripts and stylesheets, eliminates inessential characters such as spaces, newline characters, and comments; minified files are reduced by about 20%, on average.

Minification not only reduces bandwidth consumption and latency, but also may mean the difference between a cacheable object and one that is too big for the cache on a particular mobile device. Gzip compression is no help in this regard, because objects aren’t cached by the browser until after they’ve been decompressed.

7. Resize images

Images are one of the single greatest performance culprits. On mobile devices, high-res images are a massive waste of bandwidth, processing time, and cache space. To speed up page rendering and reduce bandwidth and memory consumption, dynamically resize images in your application, or replace images with smaller versions for mobile sites. Don’t waste bandwidth by relying on the browser to scale a high-resolution image into a smaller width and height.

Another option is to load a very low resolution version of an image initially to get the page up as quickly as possible, and then replace that with a higher-resolution version on the onload or ready event, after the user has had a chance to begin interacting with the page.

8. Simplify pages with HTML5 and CSS 3.0

The HTML5 specification includes new structural elements, such as header, nav, article, and footer. Using these semantic elements yields a simpler and more efficiently parsed page than using generic nested div and span tags. A simpler page is smaller and loads faster, and a simpler document object model (DOM) means faster JavaScript execution. The new tags are quickly being adopted in new browser versions, including mobile browsers. Maximiliano Firtman has created an excellent table that shows which HTML5 features are supported by which desktop and mobile browsers.

Similarly, new CSS 3.0 features can help create lightweight pages by providing built-in support for things like gradients, rounded borders, shadows, animations, transitions and other graphical effects that previously required you to load images.

OPTIMIZE CLIENT-SIDE PROCESSING

9. Defer rendering HTML

On mobile devices, attempting to load and render a page with lots of HTML can be slower than loading the HTML first and then rendering it. One approach is to enclose the HTML in a comment tag and then to use JavaScript to remove the comment, load the DOM, and render the page.

You can also assure that the user sees the page quicker by delaying the loading and rendering any content that is “below the fold” of the initially visible area. To eliminate the need to reflow content after the remainder of the page is loaded, replace images initially with placeholder img tags that specify the correct height and width.

10. Defer loading and executing scripts

Parsing JavaScript can take up to 100 milliseconds per KB of code on some mobile devices. Many script libraries (such as scripts that support interactive user behaviour, e.g. drag and drop) aren’t needed until after a page has finished rendering. Downloading and parsing these scripts can be deferred until after the onload event. The same logic applies to script execution. Defer as much as possible until after onload.

The script to defer could be your own or scripts from third parties. Poorly optimized script for ads, social media widgets, or analytics support can block a page from rendering, sometimes adding precious seconds to load times. You’ll also want to carefully evaluate the use of large script frameworks like jQuery for mobile sites, especially if you are only using a couple of objects in the framework.

11. Use Ajax for progressive enhancement

Asynchronous JavaScript with XML (AJAX) is a technique for using the XmlHttpRequest object to fetch data from a web server without refreshing the page where the code is running. AJAX allows a page to display updated data in a section of a page without reconstructing the entire page. This can enable your application to load a bare-bones version of a page quickly, and then to fill in more detailed content while the user is already viewing the page.

AJAX responses benefit from many of the same optimization techniques recommended for standard responses: cache headers, minification, gzip compression, resource consolidation, etc.

12. Implement smart preloading that adapts to the type of network connection

Some techniques should be used only when combined with code to detect the type of mobile connection. For example, preloading resources in anticipation of future requests is smart, but it may not be a responsible strategy if (1) the user’s bandwidth is metered and (2) some of those resources may never be needed.

On Android 2.2+, the navigator.connection.type property returns values that allow you to differentiate WiFi from 2G/3G/4G connections. On Blackberry, you can check the value of blackberry.network to get similar information. In addition, server-side detection of User-Agent header data or other information embedded in requests can alert your application to the type of connection in use.

13. Use HTML5 Web Workers for multi-threading

The Web Worker specification in HTML5 introduces multi-threaded concurrent execution to the world of JavaScript programming. For improving the performance of mobile sites, Web Worker code can be valuable for preloading resources that a user is likely to need to complete future actions, especially when the user’s bandwidth isn’t metered. Using multi-threaded code that employs Web Worker objects (and possibly localStorage to cache the data), operations that preload resources can execute on a separate thread without affecting UI performance.

14. Replace click events with touch events

On touchscreen devices, the onclick event doesn’t fire immediately when a user taps the screen. Instead, the device waits up to half a second (300 milliseconds on most devices), giving the user a chance to initiate some other gesture instead of a click. This delay can significantly impede the responsive performance that users expect. To fix this, use the touchend event instead. That event fires immediately when the user taps the screen.

You may still want to handle the onclick event to ensure that the browser changes the appearance of the button to show a clicked state, and to support browsers that don’t handle touch events. To avoid duplicate code execution when both touchend and onclick code fire, add a click event handler that calls preventDefault and stopPropagation if the click was the result of a user tap that was already handled by touchend.

15. Support the SPDY protocol

Some of the performance bottlenecks that afflict web sites, whether desktop or mobile, result from inefficiencies in the application-layer HTTP and HTTPS protocols. In 2009, Google began work on an alternative protocol named SPDY that addresses some of these limitations. As web servers are released that implement SPDY, your site will be able to use this protocol for any user with a browser that supports it. Google’s SPDY testing reports improvements between 27% and 60%.

As I mentioned above, this is a pretty high-level overview of these mobile-boosting strategies. If you’re looking for more background, as well as how-to information, check out Strangeloop’s mobile optimization whitepaper.


Joshua Bixby is president of Strangeloop, which provides website acceleration solutions to companies like eBay/PayPal, Visa, Petco, Wine.com, and O’Reilly Media. Joshua also maintains the blog Web Performance Today, which explores issues and ideas about site speed, user behavior, and website optimization.

Tags: , , ,

  • http://twitter.com/freitasm Mauricio Freitas

    How would you implement SPDY on a forum site where sometimes there are third party images that aren’t hosted by ourselves? This surely would cause mix content warnings?

    • Gijs

      Proxy the images through your server.

  • http://blog.justindorfman.com jdorfman

    Great post Josh, very detailed yet easy to read. HTML5 FTW!

    • Joshua Bixby

      Thanks! :)

  • http://www.leggetter.co.uk Phil Leggetter

    4 and 11 *could* be replaced with use “WebSockets as the communication protocol”.

    After the initial page load a WebSocket connection could be established (a single light weight and low latency TCP connection) and the majority of all other communication could be sent over that. And because WebSockets are bi-directional, unlike Server Sent Events (the EventSource API) which just allows server to client comms, the server and client can then communication with each other over that single low latency connection.
    The benefits here are:

    * Faster client server communication over a single low latency persistent connection. No HTTP set-up overhead for the client -> server requests.
    * A single connection, rather than multiple HTTP requests for AJAX requests and the SSE connection can lead to reduced resource (battery) usage.
    * All content can potentially be transferred over the WebSocket connection e.g. base64 encoded images
    * Work has started towards supporting WebSockets over SPDY for even more WIN

  • Steve Souders

    Wowser Josh – another awesome post! Item #9 is new to me: Defer rendering HTML. A good practice if you’re doing a lot of clientside UI construction is to avoid too many DOM interactions. One technique to achieve this is to construct all the UI as a string of HTML and then insert it into the DOM with a single innerHTML assignment. Another is to manipulate elements that are NOT in the document’s DOM and then add them to the document when all the manipulation is finished. Is that the kind of thing you’re talking about? If not, can you elaborate?

    • Joshua Bixby

      Thanks for the kind words, Steve. :)

      It’s more like the second technique you mentioned: manipulating elements that aren’t in the document’s DOM and then adding them to the document. We’ve worked with deferring everything from small portions of DOM manipulation to some whole documents. We have, at times, thought about ways of intercepting poorly written code that uses Jquery, for instance, to buffer a bunch of DOM manipulations into one buffer that makes a change at the end to prevent reflows.

      Let me know if any of this is unclear or if you want more elaboration.

  • Francisc

    Sorry, I can’t read that font.

    • Francisc

      Font problem solved, it was a browser+OS problem on my part.
      Thanks for the help. I appreciate it.

  • raji

    it was very useful me

  • solaiman
  • http://www.comp.lancs.ac.uk/~elkhatib/ Yehia El-khatib

    Helpful post. If your server supports SPDY then there’s no need to consolidate resources as the TCP connection will be multiplexed.

  • jasonm23github

    Re: SSE/EventSource am I right in thinking, only the application data transferred is getting billed by a mobile carrier, or is there incidental connection / keep-alive data going on continuously?

    I’m particularly interested because of the implications to roaming customers.