I have been doing some experiments in the HTML5 mobile app area. Read some blogs, saw some screen casts and this seems to be the recommendations for designing high performance HTML5 mobile apps:
With these in mind, I realized that using some of the existing framework (jquery mobile, or sencah touch) may not be the most optimal option. The main problem is that they are made to be cross platform, wich means they pack inside platy of code that may not be needed for particular OS, and also are designed for the lowest common denominator (this is what Steve Jobs hated), so they will never take full advantage of the specific HTML5/CSS features of a particular OS.
So here is a code sniped that does the following: first it injects sockets.io in, then loads all other resources via websockets (css js and JSON), this is in theory (and reality) much faster since there is not HTTP header overhead, and there are no limits on HTTP requests. Then CSS and JS requests are cached into local storage. Also any data communicating with the server is not done via ajax but websockets. I have discovered an interesting behavior, it's not just that it's faster over the network, but you can do an interesting loading method that is not possible in classic ajax/http: you can send a short message to the server that you would like to receive information, and then the server can start sending you the requested data in smaller chunks. This gives the app an extremely interactive look... because data can start coming from the server instantly, and "animate" on the screen.
(function(){
// Header tag.
var oHead = document.getElementsByTagName('head')[0];
// Get content div.
var contentDiv = document.getElementById('content');
// Create namespace.
window.APP = {};
// Script loader.
APP.loadScript = function(sScriptSrc, callbackfunction) {
// Gets document head element
var oHead = document.getElementsByTagName('head')[0];
if(oHead) {
// Creates a new script tag
var oScript = document.createElement('script');
// Adds src and type attribute to script tag
oScript.setAttribute('src',sScriptSrc);
oScript.setAttribute('type','text/javascript');
// Calling a function after the js is loaded (IE).
var loadFunction = function() {
if (this.readyState == 'complete' || this.readyState == 'loaded') {
callbackfunction();
}
};
oScript.onreadystatechange = loadFunction;
// Calling a function after the js is loaded (Firefox).
oScript.onload = callbackfunction;
// Append the script tag to document head element.
oHead.appendChild(oScript);
}
};
// Executes script.
APP.exeScript = function(js){
var oScript = document.createElement('script');
oScript.setAttribute('type', 'text/javascript');
oScript.innerHTML = js;
oHead.appendChild(oScript);
};
// Load css.
APP.updateCss = function(css){
var oStyle = document.createElement('style');
oStyle.innerHTML = css;
oHead.appendChild(oStyle);
};
// Local storage wrapper.
APP.storage = {
set: function(key, value) {
localStorage.setItem(key, value);
},
get: function(key) {
return localStorage.getItem(key);
}
};
// Load socket script.
APP.loadScript('http://localhost:8083/socket.io/socket.io.js', function(){
APP.socket = io.connect('http://localhost:8083');
var socket = APP.socket;
// Load css.
APP.loadCss = function(path){
// Use local storage for cashing.
var localCSS = APP.storage.get(path);
if(localCSS) {
APP.updateCss(localCSS);
} else {
socket.emit('loadFile', path, function (css) {
APP.updateCss(css);
APP.storage.set(path, css);
});
}
};
// Load some css.
APP.loadCss('jqt/themes/css/jqtouch.css');
// JS socket loader.
var require = function(path, callBack){
// Use local storage for cashing.
var localJs = APP.storage.get(path);
// TEMP ceche disabled.
//localJs = false;
if(localJs) {
APP.exeScript(localJs);
callBack();
} else {
socket.emit('loadFile', path, function (js) {
APP.storage.set(path, js);
APP.exeScript(js);
callBack();
});
}
};
// Load libs.
require('jqt/src/lib/zepto.min.js', function(){
require('/jqt/src/jqtouch.min.js', function(){
// Run your code here.
});
});
});
});
}())