Architecting Performant HTML5 Mobile Applications on Force.com: Part 2

Are you looking to architect performant HTML5 mobile apps for Force.com? In part 2 of this series of best practices from MVP extraordinaire, Keir Bowden, learn about the best ways to integrate with Force.com, render images, and more.

Part 1 of this series covered the reasons why performance matters in the mobile world, and gave some high level advice on how to re-architect applications for mobile devices. This post covers best practices around accessing data from Salesforce, using JavaScript and rendering images.

Note: This post is from Keir Bowden (aka Bob Buzzard), a Force.com MVP, Salesforce Certified Technical Architect and CTO of BrightGen, a Platinum Cloud Alliance partner in the United Kingdom. He has been solving business problems with the Force.com platform since 2008 and building hybrid and HTML5 mobile applications since late 2010. He is a regular blogger on Apex, Visualforce and Salesforce1 solutions at The Bob Buzzard Blog.

Accessing Salesforce Data Using Integration APIs

When building desktop Visualforce applications, data is created, updated and retrieved via the page controller. In the case of a standard controller, this works without writing a single line of code. As mentioned in the first post in this series, the application state is maintained by the Visualforce view state, which is not particularly well suited to mobile applications for the following reasons:

  • View state is a large resource for the device to manage, especially as mobile devices have less memory than their desktop counterparts.
  • The view state makes a full round trip to the server with each request, increasing the request size and consuming additional bandwidth which may lead to increased page load times.

When an application is re-architected for mobile devices, Visualforce is used as the page delivery mechanism, but the business logic and access to Salesforce data is handled by JavaScript executing on the device. In this case, a different mechanism for accessing Salesforce data is required, which is conceptually closer to data integration with an external system. There are three Force.com APIs available to accomplish this integration.

Web Services API

The Salesforce AJAX Toolkit provides a JavaScript wrapper around the Web Services API, allowing methods to be invoked directly from JavaScript code. As SOAP is an XML based protocol, there is an overhead in the request/response either in terms of increased bandwidth consumption in the case of connections that do not use HTTP compression, or increased CPU time to compress the messages for connections that do use HTTP compression. SOAP typically also introduces additional overhead in terms of generated parsers and handlers.

Due to the additional overhead, I try to avoid using this mechanism for an HTML5 mobile application unless the functionality that I require is only available through the Web Services API.

REST-based APIs

Salesforce provides a standard REST API, but this is built around accessing a single type of sObject per API call. For mobile applications that operate against a hierarchy or complex graph of sObjects, this requires multiple API calls to retrieve and save data, which is something that should be avoided, as explained in the first post in this series. For this reason, custom REST APIs should be created using Apex REST, which can work against the entire set of sObjects managed by the application in a single call.

A downside to accessing Salesforce via the REST API is that there is a limit on the number of API calls that may be made per 24 hours. Using custom REST APIs reduces the amount of API calls considerably, but this may still prove to be a problem, especially if there are existing integrations implemented on the Salesforce instance which may already mean API calls are at a premium. The benefit to using this mechanism is that it loosens the coupling between the mobile application and Salesforce.

Due to the consumption of API calls, I rarely use this mechanism for a Visualforce HTML5 mobile application – even if API calls are not currently at a premium in the Salesforce organization, there is no guarantee that they won’t be at some point in time in the future, and as I am tied in to Visualforce as the application delivery mechanism, the loose coupling isn’t a great benefit.

For more information on calling the REST API from JavaScript, see Pat Patterson’s post on the subject.

JavaScript Remoting

JavaScript remoting in Visualforce allows custom methods provided by the page controller to be executed directly from JavaScript. As this is a Force.com technology, it tightly couples the application to the Salesforce1 platform.

Unlike the REST API, JavaScript remoting does not consume API calls and for this reason it is my recommended method of integrating a Visualforce HTML5 mobile application with Salesforce.

NOTE: The advent of the Spring 14 release introduces the Visualforce Remote Objects pilot, which provides DML operations on sObjects directly from JavaScript. The downside to this is similar to the downside for the standard REST API described above — an application needs to make multiple requests to manage multiple objects.

For more information on JavaScript Remoting, visit the Visualforce Developer’s Guide

Rendering Images for Mobile Applications

Images have long been a thorny problem when developing mobile applications, especially for applications that are intended to run on devices with different sized screens. In this situation the images need to be responsive and sized (or resized) appropriately for the device.

Long term, the solution is highly likely to be the proposed <picture> element. This allows a page author to specify multiple sources for an image based on media queries, and the browser will choose the most appropriate source based on the device capabilities. For example:

<picture width="500" height="500">
   <source media="(min-width: 45em)" src="large.jpg">
   <source media="(min-width: 18em)" src="med.jpg">
   <source src="small.jpg">
   <img src="small.jpg" alt="">
   <p>Accessible text</p>
</picture>

Note that there is a regular <img> element nested in the picture element, providing a fallback for legacy browsers that don’t support the new element.

Unfortunately, the element is currently a W3C working draft and at the time of writing (May 2014) no browsers provide support for this. This leaves us to choose between currently supported solutions. I’ve used each of the three solutions listed below, and have settled on Picturefill for truly mobile applications.

Download and Hide

In this solution, multiple versions of each image are maintained, each version suitable for display on a device with a particular screen size. Markup in the page is provided for the complete images, and CSS media queries are used to hide all but the images specific to the device.

This is probably the worst approach for a truly mobile application, as even though the majority of the images are hidden, they have still been downloaded from the server, increasing request size and duration, consuming mobile data and increasing the size of the resources that the device browser has to manage.

 
<style>
    .logo-med {
        display:none;
        }

    @media only screen 
        and (max-width : 1024px) 
        {
            .logo-med {
                display:block;
            }
            .logo-large {
                display:none;
            }
        }
</style>

<img src="{!URLFOR($Resource.BGLogos, 'img/brightgen-logo-300px.png')}" 
class="logo-large"/>
<img src="{!URLFOR($Resource.BGLogos, 'img/brightgen-logo-150px.png')}"
 class="logo-med"/>

In the code snippet above, the large logo will be displayed when the screen size is greater than 1024 pixels, otherwise the medium size logo will be displayed. However, both images will be retrieved from the server regardless of the screen size.

Download and Shrink

This solution utilizes images that look good on the largest screen and resizes these for smaller devices via CSS media queries.

While this approach is more efficient than Download and Hide in terms of request size and data usage, it still has the potential to be extremely wasteful – reducing an image height and width by 50%, for example, means that 75% of the image is discarded. It also has the downside that simply resizing the image may make it illegible or lose the idea the image is trying to convey. For these reasons I only use this technique when building an HTML5 mobile application that will primarily be used with a high speed connection.

<style>
    .logo-med {
        width: 300px;
        height: 68px;
        }

    @media only screen 
        and (max-width : 1024px) 
        {
            .logo-large {
                width: 150px;
                height: 34px;
            }
        }
</style>

<img src="{!URLFOR($Resource.BGLogos, 'img/brightgen-logo-300px.png')}"
 class="logo-large"/>

In the code snippet above, the logo will be rendered at its natural size of 300 x 68 pixels when the screen size is greater than 1024 pixels, otherwise it will be rendered at 150 x 34 pixels. However, in both cases the full sized image is downloaded.

For more information on CSS media queries and how these can be used to alter styling, see: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries

Picturefill

Scott Jehl’s Picturefill is a polyfill for the proposed <picture> element.

Picturefill is very lightweight, weighing in at 11Kb minified and doesn’t rely on any additional JavaScript libraries. It does, however, require special markup, with spans defining the image variants and data-media attributes containing the media queries. The following code snippet defines a Picturefill span that will generate an image tag to retrieve the 300px version of the image if the screen minimum width is 1024px, otherwise it will generate an image tag to retrieve the 300px version of the image:

<span data-picture="1" data-alt="BrightGen Logo">
    <span data-src="{!URLFOR($Resource.BGLogos,
                             'img/brightgen-logo-150px.png')}"></span>
    <span data-src="{!URLFOR($Resource.BGLogos, 'img/brightgen-logo-300px.png')}"
                             data-media="(min-width: 1024px)"></span>
</span>

As the image tags are generated through JavaScript, a function must be executed to process the picturefill elements:

<script>
    window.picturefill();
</script>

As Picturefill uses JavaScript to turn <span> elements into images, no images are retrieved until after the page has been downloaded, which does introduce a delay.

In spite of this, Picturefill is my preferred solution. Retrieving only images that are suitable to the device and that are already at the correct size reduces both the size of the server responses and the amount of processing that the device has to carry out on the response.

For a more detailed discussion on responsive images in general (as opposed to mobile specific considerations) visit:

http://www.smashingmagazine.com/2013/07/08/choosing-a-responsive-image-solution
http://css-tricks.com/which-responsive-images-solution-should-you-use

Performant JavaScript

As mobile applications are primarily authored in JavaScript, it is important to write JavaScript code in a fashion that is performant without sacrificing maintainability.

Minify/Compress JavaScript Resources

Minifying is the technique that provides the biggest return when it comes to improving JavaScript performance. Minifying removes all unnecessary data that does not compromise the JavaScript functionality – whitespace, comments, lengthy variable and function names. This results in resources that are smaller and thus transfer quicker and require less time to process on device. Online tools are available to minify JavaScript, either by cutting/pasting the source into an input text area or supplying the URL to your JavaScript. Some examples are:

http://dean.edwards.name/packer
https://www.freeformatter.com/javascript-minifier.html

If you have split your JavaScript into a number of resource files, this will result in multiple requests to retrieve the resources. In this situation consider a JavaScript packer/compressor that combines these resources into a single file. Again, a number of online tools are available, which also minify the resources prior to combining them:

http://jscompress.com
http://www.jsmini.com

Keep Functions Small

Modern JavaScript engines will usually inline small functions as part of their Just In Time compilation, providing a performance improvement. This should not be at the expense of code readability and maintainability though, so it is not good practice to break complex business logic out into a huge number of function calls.

Content Delivery Networks

A Content Delivery Network (CDN) is a distributed network of servers in multiple locations, serving content to end users with high performance and high availability. When a user makes a request to a CDN hostname, DNS resolves to an optimized server based on location and availability, which handles the request.

When building Visualforce applications, there are two types of CDN to be considered:

External “Library” CDN

This type of CDN hosts multiple versions of popular JavaScript libraries.

The key benefit to using one of these CDNs is the caching of regularly used content. Using JQuery as an example, most users will have many versions of JQuery stored in their browser cache, used by applications from different sites. As these have each been served from different sites the browser will disregard these when JQuery is referenced from a new site, as it cannot reliably determine that any of the cached versions matches that on the site. When JQuery is served from a CDN, the browser can detect that it already has a cached version of the file (as the site and filename matches the cached version) and serve it from cache rather than downloading it anew.

Another benefit, although less important with modern browsers, is parallel loading. Browsers limit the number of requests that can be made in parallel to a single hostname — as little as two requests for some older browsers. By splitting resources between one or more external CDNs and Salesforce, the number of parallel requests the page can support is increased.

Examples of this type of CDN are Google Hosted Libraries and Microsoft AJAX libraries. My experience of these CDNs is that Microsoft usually has the latest versions of libraries available first, so if you need the most up to date functionality you should start there.

Including files from an external CDN simply requires the appropriate URL to be provided to the Visualforce component. The code snippet below retrieves the CSS and JavaScript resources for JQuery Mobile 1.4.2 from the Microsoft AJAX Libraries CDN.

<apex:styleSheet value="https://ajax.aspnetcdn.com/ajax/jquery.mobile/1.4.2/jquery.mobile-1.4.2.min.css" />
<apex:includeScript value="https://ajax.aspnetcdn.com/ajax/jquery.mobile/1.4.2/jquery.mobile-1.4.2.min.js"/>

Salesforce CDN

If your application is served from an unauthenticated Force.com site, or an authenticated Force.com site but not over SSL, it can take advantage of the CDN provided by Salesforce. This caches entire pages, by default for 10 minutes, on a network of over 40,000 servers around the world.

If your JavaScript and CSS resources are served as Static Resources, the Salesforce CDN will also cache these as long as they are marked as ‘Public’. Static Resources are cached for 24 hours unless a new version is uploaded, in which case it will generate a different URL, causing the new version to be cached immediately.

While serving common JavaScript libraries as Static Resources from the Salesforce CDN improves the speed of the response time, it reduces the likelihood that the device browser will have cached the file for a different application/site. Therefore I always recommend using an External “Library” CDN unless there are restrictions on access to the external sites.

For more information on Content Delivery Networks, visit:

http://en.wikipedia.org/wiki/Content_delivery_network
http://www.globaldots.com/content-delivery-network-what-you-really-need-to-know

Related Resources

About the Author

Keir Bowden (aka Bob Buzzard), is a Force.com MVP, Salesforce Certified Technical Architect and CTO of BrightGen, a Platinum Cloud Alliance partner in the United Kingdom. He has been solving business problems with the Force.com platform since 2008 and building hybrid and HTML5 mobile applications since late 2010. He is a regular blogger on Apex, Visualforce and Salesforce1 solutions at The Bob Buzzard Blog.

This post was published in conjunction with the Technical Enablement team of the salesforce.com Customer-Centric Engineering group. The team’s mission is to help customers understand how to implement technically sound salesforce.com solutions. Check out all of the resources that this team maintains on the Architect Core Resources page of Salesforce Developers.

Leave your comments...

Architecting Performant HTML5 Mobile Applications on Force.com: Part 2