Article Series
Introduction
This article is about popular challenges in web application development and their solutions.
Modern web applications could easily be decomposed into two distinct code bases. One that runs on server infrastructure and the other that runs on end user devices.
The server infrastructure could be as big as over 49,293 servers in just
one Google data center and could be as small as a website hosted on
a company's internal web
server.
Figure - Google Data Center
On the other hand, end users use web applications on myriad of devices, ranging from desktops, laptops, tablets, HDTV, printers, phone display and smart phones. All
these devices come in variety of screen sizes, native frameworks and browser compatibilities
for CSS3, JavaScript, and HTML5.
This leaves web application development teams in making variety of decisions regarding application compatibility, performance, usability and maintainability.
Let's discuss device and server side code bases separately.
Figure - One way to visualize web application
Device Codebase
Popular end user devices like laptops, tablets and smart phones could run two different kind of web applications.
- A responsive HTML website like Boston Globe which runs on all kind of devices equally well, or
- A native web application like Evernote which runs on popular smart phones
like iPhone 5, Glaxay S2,
Nokia Lumia, or BlackBerry Q10.
A responsive web application developed using HTML5, CSS3, and JavaScript could be viewed on phone browser while native web application runs directly from device.
Native apps are built using:
- Device SDK, e.g., iOS SDK, Android SDK,
Windows Phone SDK or Black Berry SDK, or
- Cross platform SDKs PhoneGap, Flex,
or Xamarin, or
- HTML 5 and JavaScript based hybrid frameworks like Kendoui Mobile,
Sencha Touch, or jQuery Mobile.
Figure - Native application developed using KendoUI Mobile and PhoneGap
Let's discuss responsive and native web applications in a bit more detail.
A. Responsive Web Application
Some web applications render on smart phones, HDTV & tablets while others do not. A public website like Netflix is viewed on
different device sizes from laptops to HDTV and smart phones. To support a
variety of device sizes while keeping a single code base, a website should use
responsive web
development technologies like CSS3 or frameworks like Bootstrap or Foundation.
Bootstrap is mostly used in those solutions where a website runs on all kinds of devices including laptops and smart phones while Foundation is more suitable for
small devices with limited storage and computing power like smart phones and tablets.
Both of these technologies are based on CSS3 and therefore by applying a simple CSS class, we can create different layouts and components. For example, by applying a few
Bootstrap CSS classes, we can create split buttons:
CSS3
High level responsive frameworks like Bootstrap or Foundation use CSS3 media queries and Unobtrusive JavaScript
to render web pages on devices with different sizes and capabilities. Consider for example, Style.css below is applied only when the device's maximum width is
480px and resolution is 163 DPI.
<link rel="stylesheet" type="text/css"
media="screen and (max-device-width: 480px) and (resolution: 163dpi)"
href="Style.css" />
CSS3 media
queries are at the heart of making web apps responsive. Media queries uses media features like device-width, device-height, orientation, device-aspect-ratio in CSS
file to develop highly responsive web apps. For example, Device.css below will be applied only to those devices which have colored screen in
portrait orientation. This gives great control over what we want to show (or don't want to show) on a particular device, orientation and
resolution.
<link rel="stylesheet" media="screen and (color) and (orientation: portrait)" href="Device.css" />
Using CSS selectors one can write very granular CSS rules. In the presence of Bootstrap, Foundation and tons of responsive themes you may not be using CSS3 directly, but remembering following CSS selectors will greatly help in understanding what you could do with CSS3 and jQuery. Checkout these interesting
examples:
div * a:hover { color: red;}
h1, h2, h3 { color: blue;}
h1[article]{ color:blue;}
h1[article="title"]{ color:blue;}
h1[article~="title"]{ color:blue;}
h1[article^="top"]{ color:blue;}
h1[article$="top"]{ color:blue;}
h1[article*="top"]{ color:blue;}
h1[article|="top"]{ color:blue;}
HTHM and therefore DOM is hierarchal, so we could select elements based on parent-child relationship (e.g., first child), their relative position (e.g., n - 1 child where
n is the last child) and element type (e.g., img, div).
div:nth-child(n-1)
div:nth-last-child(n-1)
img:nth-of-type(n-1)
img:nth-last-of-type(n-1)
div:first-child
div:last-child
img:first-of-type
div:last-of-type
div:only-child
img:only-of-type
div:empty
a.external:link {color: cyan;}
a.external:visited{color: grey;}
a.external:active{color: red;}
a.external:hover{color: white;}
input:focus {color: red;}
p:target{color: red;}
input:lang(en-US){color: red;}
input:enabled{color: red;}
input:disabled{color: red;}
input:checked {color: red;}
p.main::first-line { text-transform: uppercase }
p.main::first-letter { text-transform: uppercase }
p::before { text-transform: uppercase }
p::after { text-transform: uppercase }
div.sidebar{color: red;}
div#socialbar{color: red;}
a:not(:visted) {color: red;}
div p{color: red;}
div > p{color: red;}
div + p{color: red;}
As you can imagine a CSS3 stylesheet can get very complex and hard to manage, so there is a need of CSS preprocessors like LESS
and SASS. These preprocessors extend CSS with dynamic behavior such as variables, mixins, operations, and functions. Bootstrap uses LESS to create complex CSS rules. For example, you could define a variable and the resulting CSS will expand that variable.
Figure - LESS variable
One of the problems with CSS development is that different browsers have different "default styles" for
HTML elements like <sup>, <sub>, <h1>, <h2>, <h3>, etc.
This causes CSS to work in a browser but break in another. To avoid this problem, we could use
Reset.css or
Normalize.css. With Reset.css, the CSS developer sets
HTML
elements to some default value. However it is a less preferred method as compared to Normalize.css because Reset.css unstyles every
HTML element and removes some useful defaults. For example, the following reset will set
h1, h2, h3 and h4 font-size to 100%, which is not really useful in most cases.
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
To better address the browser defaults problems, Normalize.css corrects styling and makes it
consistent in every
browser.
CSS developers are also challenged by the various browser modes. Modern browsers support two modes for
parsing HTML and applying CSS. One is called
Strict or Standard Mode
in which the developer specifies the exact DOCTYPE. In Strict mode, the browser uses W3C specification to layout a web page.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
The other mode is called Quirks Mode, which the browser uses when no DOCTYPE
tag is used. In this mode the browser uses its non-standard rules to layout a document. One of such a non-standard rule is Box Model.
CSS developers face a good deal of problems due to differences in the Box Model implementation in various browsers.
A Box Model is fundamental to the layout a web page. A web browser creates a hierarchical tree of HTML elements (i.e., DOM) in the form of rectangle boxes as shown below.
Figure - W3C box model
Each HTML element like <h1>, <h2>, <img>, <p>, <br> gets its box.
Figure - Padding, Border, and Margin
Earlier versions of browsers, especially IE 5.x, use a different Box Model to calculate the width as specified by W3C. To render such pages, Quirks mode is
used.
The difference between W3C and the IE box model could be seen in the figure below. You can see the W3C width specification does not include padding and border.
Figure - IE vs. W3C Box Model
Currently IE10 supports various quirk modes to support old
pages. To enable IE5 quirk mode for legacy pages in IE10, use the following <meta>
tag in <head>
before any script.
<meta http-equiv="X-UA-Compatible" content="IE=5">
Figure - IE 10 Qurik Modes
For all new pages do not use quirk mode. Instead use Standard or Strict mode by specifying correct DOCTYPE. Also CSS3 provides an excellent way to overcome
the Box Model issue by using the box-model
attribute. If box-model
is set to
border-box
then element width
includes padding and borders.
p { box-sizing:border-box; width:100px; padding:10px; border:10px solid blue; }
Unobtrusive JavaScript
Discussion of Responsive Web App does not complete without Unobtrusive JavaScript.
Unobtrusive JavaScript is an umbrella term used to write JavaScript that works on large number of devices with different capabilities and one that is easy to maintain.
What this really means in one way to separate JavaScript from HTML as shown below.
<input type="text" name="date" onchange="validateDate()" />
<pre lang="jscript">function() {
document.getElementById('date').onchange = validateDate;
}
<input type="text" name="date" id="date" />
window.onload = function() {window.onload = function() {
document.getElementById('date').onchange = validateDate;
};
In sample 2 above, validateDate()
is decoupled from HTML using element id 'date
'. We can now put JavaScript in separate file(s) to
increase code maintainability. It is far easier to fix issues, add new
features and introduce polyfills in modular
JavaScript files.
Browsers are catching up with HTML 5 and CSS 3 specification and dispensing more and more support with every new version. To fill up gaps in browser
functionality polyfill is used. A polyfills is JavaScript that provides missing functionality in browser. For
example, Firefox 23, 24, and 25 do not support HTML5 Web SQL Storage and IE8 & 9 can not do CSS3 Transitions. In such cases, a polyfills provides a fallback for these browsers and supply necessary functionality. A polyfill helps in
graceful degradation of JavaScript,
which is another guideline of writing Unobtrusive JavaScript. There are dozens of polyfills available at the time of writing. You can check browser support for HTML5 and CSS3 at caniuse.com.
Also Modernizr is a JavaScript library that detects HTML5 and CSS3 features in the user’s browser. Modernizr supports dozens of tests, and optionally includes YepNope.js for conditional
loading of external .js and .css resources. This is specifically useful in loading polyfills. For example, following will load
geo.js only if the browser supports geo
location feature else a polyfill geo-polyfill.js will be loaded.
Modernizr.load({
test: Modernizr.geolocation,
yep : 'geo.js',
nope: 'geo-polyfill.js'
});
We can easily predict that an unobtrusive JavaScript results in fast page loads due to
a smaller HTML file. It is possible to further increase page load
speed by JavaScript minification,
compression, and deferred loading which is very important for contents targeted for smart phones, tablets and other devices with limited bandwidth, storage and computation power.
Minification is a process to combine multiple CSS or JavaScript files, remove unnecessary whitespace and comments. There are online tools available which not only minify CSS or JavaScript but also serve them with gzip encoding
and optimal client-side cache headers. Such JavaScript/CSS files could also use CDN and browser cache effectively to further shorten page load time.
Figure - What is Deferred Page Loading?
Heavy usage of JavaScript libraries resulted in deferred page
loading techniques. A webpage won't display until all your JavaScript is downloaded, this causes severe delays unless it is deferred properly. A page will load faster if we download 'certain' JavaScript files on
page load event like click events .js file. A simple JavaScript could defer loading easily.
<script type="text/javascript">
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "deferredfunctions.js";
document.body.appendChild(element);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>
jQuery is a popular library that helps in writing unobtrusive JavaScript. Consider for
example, it is really intuitive in jQuery if you want to chain together the selection of a paragraph id p1, changing its color to red and then sliding it up
and down. Try this example here.
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<script>
$(document).ready(function()
{
$("button").click(function(){
$("#p1").css("color","red").slideUp(2000).slideDown(2000);
});
});
</script>
</head>
<body>
<p id="p1">jQuery is fun!!</p>
<button>Click me</button>
</body>
</html>
Not only this, jQuery simplifies AJAX calls, DOM events attachment, and element
selection. It uses Sizzle as its CSS selector engine. Sizzle supports
almost all CSS3 selectors discussed earlier in this article.
Writing JavaScript could be challenging for new comers as it has has type coercion. Numbers can become strings, strings can become numbers, and arrays can become strings. Checkout below why empty string - 1 = -1 in JavaScript:
var x = "" - 1; var a = []; ++a;
To avoid type coercion and to increase code
maintainability, unobtrusive JavaScript guidelines prefer === and !== operators as compared to their 'evil twins' == and !=. === does not convert
type while == converts type before comparison.
Consider some difficult to guess JavaScript conditions in code below:
undefined == null NaN == NaN 2 == "2" false == 0 true == 1 true != 2
While comparing objects to primitive type JavaScript calls
valueOf()
if primitive type is number else it calls toString()
.
var amt = {
valueOf: function () {
return 10;
}
};
amt == 10 var amt = {
toString: function() {
return 20;
}
};
amt == 10
var undefined = 10;
alert(undefined);
var arg = 0;
if(typeof arg == 'undefined')
alert ('arg is not defined');
else
alert ('arg is defined');
alert(Math.min() < Math.max()); alert(typeof NaN)
Figure - JsFiddle in Action
JavaScript coercion, loose type system and OOP syntax (which is different as compared to popular languages like Java, C#) has created programmer's outcry
which could be felt here. JsFiddle is one of popular ways to play with JavaScript and Jslint
to measure its quality. There is even an online tool
to beautify your JavaScript code.
Figure - Chrome Developer Tools
Chrome provides a built-in support to debug JavaScript and CSS and it
comes very handy when debugging and tuning JavaScript.
JavaScript coercion made people to write all
kinds of transcompilers to convert language of your choice into JavaScript. Some of them are CoffeeScript, Microsoft TypeScript, Objective-J, Google DART and many others.
Among these Microsoft TypeScript is interesting being a strict superset of JavaScript (like C++ is for C)
and probably the future of JavaScript i.e. ECMAScript Harmony (6th Edition). TypeScript supports
OO syntax and is strongly typed, so code completion and compile time type checking is possible.
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
You can see it is far easier to comprehend TypeScript OO syntax as compared to JavaScript.
Google DART on the other hand is a totally new language which
compiles into JavaScript. Like with other
preprocessors, debugging DART generated JavaScript and using existing JavaScript libraries pose a challenge.
CoffeeScript, inspired by Python/Perl, is like TypeScript and and
it compiles into JavaScript. It is widely used as an alternative of JavaScript and claims to reduce code to 1/3. Checkout
this comparison of Coffeescript vs. Typescript vs. Dart.
Figure -
Selling “Samy is my hero” T-shirts
With the popularity of JavaScript, Cross Side Scripting (or XSS) and Cross-site Request Forgery (or CSRF) attacks have become common. There are many people who
may still remember Samy Worm at MySpace that shut down the popular social networking site for two and
half hour when its creator was able to receive 1 Million friend requests in less
than 24 hours.
Open Web Application Security Project provides a good starting point to
sanitize your application against XSS and CSRF attacks. Microsoft provides Microsoft Web Protection Library to encode user input, including HTML, HTML attributes, XML, CSS, and JavaScript. One way to test
your site for XSS and CSRF issues is to use BEEF.
But as a summary, never put untrusted data at following locations and 'escape' with some
library like Microsoft Web Protection Library:
<!---->
<span>...NEVER PUT UNTRUSTED DATA HERE...</span>
<script>...NEVER PUT UNTRUSTED DATA HERE...</script> directly in a script
--> inside an HTML comment
<div>...NEVER PUT UNTRUSTED DATA HERE...</style> directly in CSS
<input type="text" name="fname" value="...NEVER PUT UNTRUSTED DATA HERE.../>
<a href="/site/search?
value=...NEVER PUT UNTRUSTED DATA HERE...">clickme</a>
-->
<iframe src="UNTRUSTED URL" />
-->
<div style="width: ...NEVER PUT UNTRUSTED DATA HERE...;">Selection</div>
-->
<script>var currentValue=<script>someFunction(
HERE...
<!--HTML Body -->
<div>UNTRUSTED HTML<div>
<!--DOM XSS -->
<script>document.write("UNTRUSTED INPUT: " + document.location.hash);<script/>
While XSS attacks on smart phones and tablets could be minimized using the above practices, there are reports that Apple, Google, and Microsoft are building huge databases
for their location services by illegally tracking user location. :)
What's Next
In the next part I will discuss JavaScript OO and popular JavaScript frameworks like Knockout, Bootstrap, Angular etc., and what problems they solve. I will also discuss HTML 5
and its role in the development of Responsive Web App.
After completing this discussion we will see what are the challenges of using native and hybrid frameworks for solutions targeted for devices with limited storage and computing power.
Lastly, we will cover Server Code Base and challenges and solutions over there, and the role of intranet infrastructure
on the scalability, availability, and performance of a web application.