Table of Contents
The ever-evolving era of mobile compatible web apps has encouraged developers to look after the bare minimum of optimizing their web applications for the wide range of mobile devices.
In their attempt to get closer to the native applications, developers often get distracted by issues like choppy page transitions, periodic delays in tap events and spinning refreshes, to name a few. Today’s post serves as an easy-to-follow guide for all such web developers who are bothered about timely mobile optimization of their HTML5 web apps but have to face some serious hidden complexities.
Let’s begin with understanding Hardware Acceleration in a better way
Typically, the GPUs look after the 3D modeling or CAD diagrams, but if you’re inclined on making your drawing, for eg: backgrounds, images, divs etc. to appear and animate via the GPU, then it isn’t recommended to rely on a third-party framework for the same. Here are some solid reasons why you need to care about masking of core CSS features:
a) Power consumption is a major concern during mobile web app development. Since browser markers enable access to a wide range of mobile devices, it is important for the developers to pay special attention of the numerous device constraints.
b) As a developer, if you go ahead with compositing every element within DOM, then the next developer who’s supposed to be working on your code may cause you a lot of trouble at a later stage.
c) If you’ve already accelerated certain parts of your web pages and are intending to apply hardware acceleration on new parts, then it is essential to know the ‘overlapping’ hardware acceleration.
In order to make the user interaction smooth and close to native, it is important to make the browser fully functional. Since we want mobile device CPU to go ahead with setting up initial animation, GPU looks after compositing multiple layers during the animation process.
Page and Resource Caching
You can go ahead with pre-fetching and caching your web pages using the concurrent AJAX calls. The basic reasons for doing the same include:
a) When it comes to pre-fetching the pages, it basically allows you to take your web app offline, in addition to enabling the no waiting between navigation actions. Since you don’t want to choke the device bandwidth, using the pre-fetching feature becomes mandatory.
b) Using innerHTML() for inserting AJAX response into DOM is quite unreliable. Instead, you can opt for a much more reliable technique for handling concurrent calls and inserting AJAX response. Additionally, you can use the HTML5 features for parsing xhr.responseText.
The key steps associated with pre-fetching and caching are listed out below:
Step 1 – Here is the semantic markup wherein I’ve used data-* attribute for “page” nodes. You need to know that the detail page(child) is located within a separate html file that would be loaded, cached and finally setup for transition once the web application loads on the device.
[php]
<div id="home-page" class="page">
<h1>Home Page</h1>
<a href="demo2/home-detail.html" class="fetch">Find out more about the home page!</a>
</div>[/php]
Step 2 – Next, there is a JavaScript wherein you won’t find any helpers or basic optimizations. In this code, you’ll find that I’ve looped through a particular array of DOM nodes so as to extract links for fetching and caching purpose. For this tutorial, I’ve used the fetchAndCache() method which is being called on page load.
[js]
var fetchAndCache = function() {
// iterate through all nodes in this DOM to find all mobile pages we care about
var pages = document.getElementsByClassName(‘page’);
for (var i = 0; i < pages.length; i++) {
// find all links
var pageLinks = pages[i].getElementsByTagName(‘a’);
for (var j = 0; j < pageLinks.length; j++) {
var link = pageLinks[j];
if (link.hasAttribute(‘href’) &&
//’#’ in the href tells us that this page is already loaded in the DOM – and
// that it links to a mobile transition/page
!(/[\#]/g).test(link.href) &&
//check for an explicit class name setting to fetch this link
(link.className.indexOf(‘fetch’) >= 0)) {
//fetch each url concurrently
var ai = new ajax(link,function(text,url){
//insert the new mobile page into the DOM
insertPages(text,url);
});
ai.doGet();
}
}
}
};
[/js]
Step 3 – Now, here is an example which displays the basic usage of caching on each request, in addition to ptoviding the cached objects each time the server returns a successful(200) response:
[js]
function processRequest () {
if (req.readyState == 4) {
if (req.status == 200) {
if (supports_local_storage()) {
localStorage[url] = req.responseText;
}
if (callback) callback(req.responseText,url);
} else {
// There is an error of some kind, use our cached copy (if available).
if (!!localStorage[url]) {
// We have some data cached, return that to the callback.
callback(localStorage[url],url);
return;
}
}
}
}
[/js]
Here, it is important for you to note that localStorage uses UTF-16 for character encoding and hence each byte is being stored in the form of 2 bytes, thereby bringing the storage limit from 5MB to nearly 2.6MB in total.
Handling Network Type Detection during mobile optimization of HTML5 web apps
Now that you’ve learnt thetechnique of pre-fetching and caching your app pages, it is important for you to provide appropriate connection detection features that can make your app more effective for the end user.
Have a look at the below code which addresses multiple network connection scenarios:
[js]
window.addEventListener(‘load’, function(e) {
if (navigator.onLine) {
// new page load
processOnline();
} else {
// the app is probably already cached and (maybe) bookmarked…
processOffline();
}
}, false);
window.addEventListener("offline", function(e) {
// we just lost our connection and entered offline mode, disable eternal link
processOffline(e.type);
}, false);
window.addEventListener("online", function(e) {
// just came back online, enable links
processOnline(e.type);
}, false);
[/js]
The above code will do the following:
a) Detect if the app has been bookmarked and is offline
b) Provide offline access via applicationCache
c) Detect slow connections and fecth the content on the basis of selected network type
d) Detect when the app is switched from offline to online mode and vice-versa
Additionally, all the events and loading scenarios are being detected using the above code snippet. In the EventListerners, we inform whether the code has been called from an event or an actual page request. This is done simply because the body onload event doesn’t get fired while the app switches from online to offline mode and vice-versa.
Next, you can use a simple check for an onload or online event. The below code will reset all the disabled links while switching from offline to online mode. The code associated with the same is shown below:
[js]
function processOnline(eventType) {
setupApp();
checkAppCache();
// reset our once disabled offline links
if (eventType) {
for (var i = 0; i < disabledLinks.length; i++) {
disabledLinks[i].onclick = null;
}
}
}
[/js]
Next os the processOffline() which would alter the HTML5 web app for offline mode in addition to recovering transactions that were being handled in the background. The below code extracts the external links, followed by disabling them, thereby keeping users trapped in the offline app:
[js]
function processOffline() {
setupApp();
// disable external links until we come back – setting the bounds of app
disabledLinks = getUnconvertedLinks(document);
// helper for onlcick below
var onclickHelper = function(e) {
return function(f) {
alert(‘This app is currently offline and cannot access the hotness’);return false;
}
};
for (var i = 0; i < disabledLinks.length; i++) {
if (disabledLinks[i].onclick == null) {
//alert user we’re not online
disabledLinks[i].onclick = onclickHelper(disabledLinks[i].href);
}
}
}
[/js]
So, now that your app is well aware of its own connected state, you can go ahead with checking the type of network connection when the app user is online and adjust in accordance to the same.
Conclusion
With that it’s a wrap on this post which elaborated on some simple HTML5 techniques that allow you to address the core features effectively. Do abide by the above guidelines and your HTML5 web app would run flawlessly on varied mobile devices.