Increasing Mobile Web Time-to-Glass
Posted on Wednesday, June 25, 2014 at 4:51PM by Jack Servedio
On the new, ever expanding, 4G networks transfer speeds are nearly on par with typical residential internet connections, yet websites can take 10 times as long to download, or more, on a mobile device. This all boils down to network latency on mobile networks. On even a modest residential internet connection, latency within the US in most cases will be 30-100ms, however, even on the fastest 4G networks in places like Manhattan or San Francisco, latency will normally be north of 200ms to even geographically close servers. On slower 4G networks or 3G networks, latency continues to climb. At my last company, average latency within the US between customers and our servers in the AWS cloud was right around 500ms, and that's within the US. Worldiwde, it was closer to a full second and a half.
Coupled with these extreme latencies is the limitation on the maximum number of concurrent connections - most mobile browsers allow for a total of 4-6 concurrent connections. On a typical Android Gingerbread device, even a major national mobile website like mobile.nytimes.com will spend just about 5 seconds loading in just latency alone due to it's 38 individual resources (not including all of the additional XHR requests). Even a site like this, which is a relatively large size for mobile, with around 350k worth of resources, transfer time would take less than half of a second on even a sluggish 3G network. Clearly, reducing the actual size of the site woudln't improve things here.
After doing this, things start to get a little more complicated - but there are plenty of options to chose from. The ultimate goal should be reducing the number of initial resources to 4 (or less) so the initial site can be loaded with the smallest possible latency penalty. Typically, the largest number of requests on a site come from the images - and this is where the bulk of the work lies. For static images such as buttons, backgrounds, logos, etc. the obvious solution is to create a single sprite.
What about dynamic images like product thumbnails? When it comes to these types of images there are three good solutions - all with their own advantages and drawbacks. However, there is no reason you can't use any combination of these as needed.
- The easiest and most obvious of the two solutions is to load them after the site has been displayed using AJAX. This is great since it requires no additional server overhead or bandwidth from the end-user. But, AJAX requests are subject to the same latency issues and maximum concurrent requests limitation and will require time to be displayed. While the site will be loaded and useable, the end-user will still have to wait to see these images and this impacts the user-experience.
- The next, less obvious solution is embedding the image data itself into the site using base 64 encoding. This can allow every single product image to be downloaded with the initial site without adding a single request. There are two main drawbacks to this solution: the first being base 64 encoding an image will increase the image size roughly 1/3 and require more of the end-user's available data. However this is mitigated by the fact that you are eliminating the latency all together. The second, and bigger issue, is that it isn't universally supported - while iOS, Android, Blackberry, and Windows devices do support it, some older Java devices do not. Again, this can be mitigated as well. When an unsupported device processes the image data, it will attempt to download a file that has the name of the image data. With a little creative URL Rewriting, the end user can still be displayed the image - it will just have to be processed like a regular request.
- The last solution is to create on-the-fly image sprites. The obvious drawback to this is the overhead required on the server generating all of these sprites, but this overhead can be eliminated by caching the sprites. The main advantages of this over the other two is that the images will be displayed immediately, there will be no compatibility issues, and no additional user-data is required. However, as the total number of images increases, the total number of possible sprites increases exponentially and this solution can only scale so far.
The last source of requests come from things like tracking pixels, ads, and other external sources. While many sources of tracking scripts and ads understand the importance of latency and make their requests in the background using AJAX, not all of them do. Ensure that every external request on your site is happening in the background long after your own resources are served and available to your customer. Never let a hanging request for an ad prevent an important resource like the sprite containing your logo from loading. Managing the external scripts running on your site properly can be just as important as managing your own resources. Never just copy and paste a script tag from a vendor without thorougly testing it's impact on your site.