Client-Side Frameworks - Client-Server Web Apps with JavaScript and Java (2014)

Client-Server Web Apps with JavaScript and Java (2014)

Chapter 5. Client-Side Frameworks

You know also that the beginning is the most important part of any work...for that is the time at which the character is being formed and the desired impression is more readily taken.

—Plato

Overview

In the early days of the Web, starting a new web page involved opening a text editor and creating an HTML document from scratch. This approach still works for creating minimal examples for educational purposes or testing isolated bits of JavaScript functionality. However, this starting point is not the place from which most modern web applications originate. Instead, a viable project template includes a well-organized directory structure and some combination of a particular set of JavaScript libraries, CSS files, HTML, and other assets. The selection might vary from project to project, but in general should address concerns such as project consistency, cross-browser compatibility, sound design principles, software development practices (such as unit testing), and superior performance.

Historically, starter projects have been generated (by tools like Maven, utilizing archetypes) or specified during the creation of a new project in an IDE. Such projects were often tied to the tool that generated them. With no standard IDE or build tool for web development, starter projects have no such tie (though are integrated in tools and IDEs). They vary in complexity and purpose, but successful ones have a common characteristic of being simple to understand, set up, and deploy. They provide a basic infrastructure that reduces tedious manual work not directly related to the main purpose of the web application.

The choice of a starting point involves the fundamental building blocks of a client-side web page: HTML, CSS, and JavaScript in the context of a web page running in a web browser. This is shown in Figure 5-1.

Client-side web page

Figure 5-1. Client-side web page

The widest context to consider is the client itself. There are many possible web browsers. Each browser has many versions. Browsers are no longer specific to desktop applications, but run on mobile devices. Each browser instance runs on specific hardware that can have a wide range of capabilities. The hardware can vary in processor power, disk space, memory, screen size, and display characteristics. This is perhaps obvious, but often forgotten by a developer whose view is restricted to a few browsers running on a developement workstation.

Starter projects can be oriented toward specific content, style, and/or behavior. HTML defines the fundamental structure and content of the page. CSS defines style and design presentation. JavaScript provides behavioral capabilities. Those with design skills might opt for a starter project that is more minimal or provides more flexibility in CSS stylings, but might want a JavaScript infrastructure that supports a wide range of plug-ins and requires minimal programming. A developer might choose a project that provides a passible design out of the box, but be comfortable with a bleeding-edge JavaScript library that takes advantage of the latest browser capabilities.

The choice of a starter project is also based on your application requirements and your audience. The goal of compatibility over the largest selection of available browsers might suggest one starter project, while the goal a highly optimized application for specific mobile devices would suggest another. For example, frameworks like PhoneGap include starter projects that specifically target mobile devices. If your project is a game or other graphically intensive project such as a simulation, starter projects that include JavaScript libraries with graphics and physics engine capabilities are relevant.

Specific requirements can suggest a starting point that is not immediately apparent or popular. It is easy to become enamoured with a particular framework or design trend, but a project’s idiosyncracies might require a different approach. For instance, if you need to actively target a particular browser (due to in-house browser standards, target web demographic, and so on), you might orient development to its particular quirks and choose a starting project that accounts for these. In addition, HTML, CSS, and JavaScript can be used to develop a range of applications outside of a standard web page such as browser extensions and native applications. A general-purpose approach targeting a range of browsers and devices is often optimal, but it is certainly not the only valid one.

In general, most serious web development projects today are intended to be fully featured applications that work on variety of devices. Most are also created with an expectation that they will grow to be relatively large and sophisticated. This suggests the use of a client-side JavaScript framework related to standard software patterns and code organization. Differences in display, browser capabilities, and device functionality imply the use of well-thought-out design that adapts to a range of devices and degrades gracefully when features are not available. The range of target device features that are expected to be leveraged over the life of the application imply the use of additional libraries and frameworks. These did not need to be considered in traditional, limited desktop browser applications.

THE HIGH COST (OR VALUE) OF EARLY DECISIONS

This section might seem to belabor the obvious. Pick a starter project and let’s roll!

The issue at stake in making well-thought-out early choices has its roots in their huge impact down the road. The idea is expressed by economists and social scientists using the term path dependence. The basic idea is that early decisions are a “disproportionate cause of later circumstances.” Problems introduced early in a project might be impossible to reverse at a later point. For instance, a choice of an immature JavaScript library can lead to numerous fixes and hacks being added to address browser incompatibilities. Though not obvious during initial development (where developers have focused attention on modern browsers), later support can become burdensome, and the large amount of additional code can lead to a situation where there is no turning back. Conversely, a well-thought-out starter project can reduce the support burden significantly far into a project’s implementation.

Starting Point One: Responsive Web Design

On May 25, 2010, Ethan Marcotte’s article titled “Responsive Web Design” appeared on A List Apart. Responsive Web Design (or RWD) has now become a general term used as a shorthand to capture the ideas he expressed. Rather than designing specifically for each device display, this style of design strives to provide an optimal viewing experience across a wide range of devices. Like software design patterns (which were inspired by Christopher Alexander’s architectural patterns), the concept finds its origin in building architecture. Responsive architecture considers how physical spaces can adapt as people pass through them. Responsive Web Design seeks to adapt to user experiences on a variety of device displays with diverse methods of interaction based on device capabilities. Three components of RWD are:

Fluid grids

Adapt the typographic grid for use on the Web. They take advantage of relative sizing available in CSS to provide display of a grid and its components in a manner properly proportioned to its context.

Flexible images

Include using the CSS max-width to cause images and other media to render within their containing element and related techniques to avoid fixed-point styling that does not adapt to all device displays.

CSS3 media queries

Inspect the physical characteristics of the context where the page is rendered and respond with a specific display fixed-unit format.

The fluid layout and flexible images (which rely on relative sizing) combined with CSS3 media queries (allowing adaptive layout targeting fixed sizing) provide the basis of RWD. Fluid layout is proportionately scaled, and adaptive layout breaks at given points. This prevents the skewing that occurs with a fluid approach alone or the lack of adaptation to intermediate display possibilities from a purely adaptive design.

By using the three constructs of RWD, a single well-constructed set of web resources can produce pages that can be viewed and used effectively on a variety of devices. Marcotte later developed the ideas introduced in the article in a book on the subject. A number of projects have been developed based on these principles, among them HTML Boilerplate and Twitter Bootstrap.

HTML5 Boilerplate

HTML5 Boilerplate provides a set of resources that satisfy the requirements of RWD. Its features include a standard directory structure and template files related to a website and web server configuration. It includes CSS that incorporates normalize.css (a stylesheet that provides consistent rendering in line with modern standards across browsers), some additional CSS defaults, common helpers, placeholder media queries, and print styles. The jQuery and Modernizr JavaScript libraries are provided as well.

Bootstrap

Twitter Bootstrap, was initially described by its creators as “a front-end toolkit for rapidly developing web applications. It is a collection of CSS and HTML conventions. It uses some of the latest browser techniques to provide you with stylish typography, forms, buttons, tables, grids, navigation and everything else you need in a super tiny (only 6k with gzip) resource.”

As such, it goes beyond the minimal resources provided in HTML5 Boilerplate. It was further enhanced in the second version and continues to be refined with input from the community that has grown around the project. Sites built with Bootstrap have been critiqued as being monotonous and predictable, essentially carbon copies of one another. Although similarity is to be expected due to the use of standard resources and styles, there is actually a great deal of flexibility available through manual customization or the use of themes. The framework has also become more “componentized” over time so that certain features can be included and excluded, and generators exist that can be used to create an out-of-the-box set of resources to differentiate it from the default.

There are many other similar projects. Zurb Foundation has a smaller user base and claims a primary target of mobile devices. If you are interested in a more lightweight project that incorporates minimal responsive design and a basic grid system with some basic styling, Skeleton might be worth checking out. But if you are working on a project that simply requires a responsive site with professional, balanced styling, Bootstrap (augmented with a theme and a few manual adjustments) is the best supported choice for the moment.

Starting Point Two: JavaScript Libraries and Frameworks

As a language matures, various standard libraries are added. In JavaScript, libraries don’t require any special structure or packaging; they are simply other JavaScript files. Libraries have been created for almost every purpose you can imagine. But there are a few broad categories of general-purpose libraries that are applicable to client-server web applications.

Browser Compatibility

Although JavaScript is a de facto standard, the idosyncracies of certain browsers are the stuff of legend. The likelihood of browser vendors creating compatible implementation is small. There is too much effort dedicated to differentiating each browser and implementing functionality geared toward driving the standards process rather than adhering to estabilished standards or guidelines. Fortunately, a number of libraries in common use smooth over many of the rough edges and result in JavaScript code that provides consistent results (and less errors or disruptive results) regardless of the particular browser version. These libraries are shown in Table 5-1.

Table 5-1. Browser compatibility

Library

Purpose

jQuery

DOM traversal and manipulation

Modernizr

Browser feature detection

Underscore

Utility functions including object and array manipulation

jQuery and Modernizr are de facto standards in their particular realm. Underscore is a bit less established. There are a number of other libraries that provide similar functionality: consistent handling of objects and arrays in a concise, functional manner (Lo-Dash, for example, is intended to be an optimized replacement for underscore).

Frameworks

Direct DOM manipulation (á la jQuery) is a fine approach with small- to mid-sized JavaScript projects. With larger projects, it is much easier to manipulate JavaScript classes that incorporate interactive data and include additional functionality, such as data validation. These classes can then be populated and connected to the graphical elements in a page. This type of design has the beneficial effect of avoiding direct DOM manipulation. Instead, changes to the data are reflected on the page based on the state of the data in the containing objects. Interaction with the page (and data changes due to external events) result in changes to the state of the model that trickle down to all affected view components. The first MVC frameworks were created many years ago for this purpose, and the pattern has been adopted in modern JavaScript frameworks. There are several variations of MVC, which include Model-View Presenter (MVP) and Model-View ViewModel (MVVM) and so the term MV* is sometimes used as a general umbrella to identify these patterns as a group.

The choice of an initial framework can be rather daunting from the outside. If you do not have a particular bias, it can take a bit of effort to make a decision about which one to use. Some basic criteria beyond current in-house development skills are the functionality of a given framework and its popularity.

Functionality

The list of MV* frameworks is rather extensive and constantly changing. One site that provides immediate specific comparison of the functionality of popular frameworks is TODO MVC. TODO MVC allows you to compare the implementation of a simple fully functional TODO list application in a variety of different MV* frameworks.

Popularity

Although the most popular selection might not be the best, it is a reasonable proxy for general support for a project and whether it has a viable ecosystem for education, enhancements, and bug fixes. Google Trends displays the number of searches being made for certain search terms, and the number of StackOverflow tags can also give an idea of developer chatter on a subject. To get a better sense of what code is actually in use, view popular GitHub repos (and statistics on new projects that have not yet catapulted to the top of the list) or get a sense of total deployment base using statistics from a site like BuiltWith.

If you decide to work with one of the major JavaScript MV* frameworks, you will want to review and possibly start with whatever project the community has produced and actively supports. Table 5-2 lists starter projects for several popular frameworks.

Table 5-2. Starter projects for JavaScript MVC Frameworks

Framework

Starter project

Backbone

Backbone Boilerplate

Angular

Angular Seed

Ember

Ember Starter Kit

Each of these frameworks is rather extensive and an exhaustive overview is not possible here. O’Reilly’s books on Angular and Backbone go into much greater detail.

These are by no means the only options. JavaScript frameworks have dependencies and inspire libraries that extend their core functionality. jQuery is a prerequisite to many other projects, and underscore.js is a dependency for Backbone. Backbone developers tend to use require.js for script loading and code organization; it also inspired the alternative MV* framework Spine. Angular-UI provides user interface components. jQuery has inspired an entire ecosystem of related libraries, plug-ins, and extensions, among them large libraries such as jQuery UI that provide widgets of all kinds and small specialized libraries like TouchPunch for touch screen event handling.

There are also starter projects, which combine a JavaScript library with another starter project oriented toward browser compatibility and responsive design. A project that combines Angular UI and Bootstrap is available and comparable to one created for jQuery UI and Bootstrap.

Beyond MVC frameworks, if you are creating a jQuery plug-in, the jQuery Boilerplate can be used to set up a properly structured project for that purpose. The bottom line is that if you find yourself writing boilerplate code for a task that you are confident others have encountered, it behooves you to check around online to find out if starter projects exist.

Obtaining Starter Projects

There are a couple of different ways to obtain a starter project to jumpstart your development.

Download Directly from Repositories

Most of these projects are maintained online in public source code repositories (generally at GitHub).

GITHUB REPOSITORY HALL OF FAME

For that matter, starter projects, resources that promote responsive web design, and JavaScript libraries are among the most popular repositories on GitHub.

§ Responsive design resources

§ Modernizr

§ Normalize CSS

§ Starter projects

§ Bootstrap

§ HTML5 Boilerplate

§ JavaScript libraries

§ jQuery

§ Backbone

§ Foundation

§ Angular

§ Underscore

§ Ember

§ jQuery UI

§ Knockout

Download from Starter Sites

Sites like Initializr or HTML5 Reset ultimately rely on source code repositories, but include commentary, comparison, and documentation related to starting web projects and general development and design topics as well.

IDE-Generated Starter Projects

IDEs like WebStorm (a commercial project created by JetBrains) include options to create new projects from templates, as shown in Figure 5-2. WebStorm includes several of the starter projects discussed in this chapter as well as Node.js (Node.js boilerplate and Node.js express) or Dartstarter projects.

Client starter projects

Figure 5-2. Client starter projects

The Rise of the Front-End Engineer

By now, it should be clear that the degree of sophistication involved with web development has expanded greatly from its humble beginnings. It is unlikely that a designer without significant developer skills and focus will be capable of keeping up with the latest advances. Likewise, it is unlikely that most server-side developers will have mature design abilities or an awareness of recent developments that are focused on the client side. This has given rise to a new occupation: the front-end engineer. If the topics introduced to this point don’t convince you of the explosion of new information, consider these additional nuances related to client-side development and processes.

Client-Side Templating

Some of the JavaScript frameworks previously discussed bundle a JavaScript templating solution. A wide variety of others exist independently, many of which can be swapped in at your discretion with a variety of frameworks. LinkedIn engineering considered 26 client-side templating technologies before settling on dust.js. There are some fascinating developments in this area, including the possibility of implementing client-side JavaScript templates that can failover to server-side rendering if needed.

Asset Pipelines

Old-school web development involved simply editing and including relevant assets on the web server. Resources can now be provided externally through Content Delivery Networks (CDNs). In addition, rather than simply editing and including the resources, they are commonly now preprocessed in a variety of ways prior to being served on the web server. An asset pipeline can be used to precompile, concatenate, and minify applicable web resources and take relevant actions related to managing the caching of these resources.

Asset compilers emerged in the Ruby community in the last several years. Early examples were Jammit and Sprockets. Later, asset pipelines were incorporated into Rails and have been adopted by web frameworks in other languages such as Java’s Play2.

Asset pipelines are used for a number of tasks. Some are geared toward reducing network latency when serving large files. JavaScript and CSS files can be minified (removing whitespace and other extraneous characters), concatenated (resulting in fewer total network calls), and compressed (using gzip or other compression algorithms). Others relate to caching. For example, the Play framework uses ETag HTTP Headers to append a value generated from the resource name and the file’s last modification date and also provides the option of setting Cache-Control headers.

In addition, having a preprocessing step available opens up the possibility of compiling other languages to JavaScript (such as CoffeeScript and Dart). This provides a range of possibilities for those who find the JavaScript language itself distasteful.

CSS can also be preprocessed, which reduces the amount of duplicated code. Less duplicated code makes the application styling more easily maintainable at the expense of adding an additional build step. A precompiler processes an initial file at some point prior to being referenced in an HTML page and resolves references in the code so that a standard stylesheet is rendered. Examples of the type of preprocessing available through a CSS compiler include:

§ Definition of variables that replace values throughout a stylesheet (for example, a color used in various CSS classes)

§ Creation of methods to assign a set of values to a class based on a variable passed as an argument

§ Implementation of inheritence of CSS classes

CSS processors originated among Ruby developers but have been gaining acceptance in the Java community. For instance, a LESS CSS Maven plug-in has been created.

The precompiling step involved in the implementation of an asset pipeline is somewhat controversial. Designers who have never only worked with hardcoded CSS files can find the programming possibilities introduced by a preprocessor daunting. And though developers are likely to be more accepting of the concept of a preprocessor (based on their usage in other programming contexts), changing anyone’s workflow can be disconcerting. This is where a new role, that of a front-end engineer, serves a needed role in bridging the gap between developers and designers. This role includes a unique workflow and set of tools suited for the expansion of responsibility that has occurred on the client tier.

Development Workflow

A node-based package called Yeoman provides a development workflow utilizing three tools: yo (for scaffolding), grunt (for building), and bower (which provides package management). Other node-based packages such as karma (for running tests) and Docco (for documentation) also apply to development worflow and build processes.

Project

In the interest of seeing the value of the simplest possible example of a framework along with how it relates to fully featured starter projects, consider the following examples using Angular:

<!doctype html>

<html ng-app>

<head>

<script src="http://code.angularjs.org/1.0.6/angular.min.js"></script>

</head>

<body>

Angular Expression 1 + 2 evaluates to: {{ 1 + 2 }}

</body>

</html>

The use of the Angular framework is immediately apparent because there are a number of XML attributes (called directives) that are not part of standard HTML included in the document. In this example, ng-app (in the HTML tag) is required to auto-bootstrap an app. One attribute of this type can appear per HTML page. It designates the root of the application and (though it is empty in this case) can optionally include a module name. The script tag indicates that Angular is in use; other Angular scripts that provide additional functionality might also be included. Finally, the bit of visible Angular functionality that will be demonstrated is an expression. An Angular expression is JavaScript-like code snippets placed in bindings (double braces) that are evaluated to produce output.

This is a very minimalistic example that only evaluates an expression. It does not even demonstrate Angular as an MV* framework as it includes no controller or data binding. It simply serves to illustrate the absolute minimum features required to create an Angular application. The next example incorporates a model and controller:

<!doctype html>

<html ng-app>

<head>

<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js">

</script>

<script>

function HelloCntl($scope) {

$scope.name = 'World';

}

</script>

</head>

<body>

<div ng-controller="HelloCntl">

Your name: <input type="text" ng-model="name" />

<hr/>

Hello {{name}}!

</div>

</body>

</html>

A controller in Angular is simply a function used to implement behavior in a given scope. In this case, the controller is used to bind a model (the name variable) that can be modified in a text field. Each time a keystroke is registered in the input text field that references the “name” model, the change is reflected in the expression referencing the model. A significant remaining bit of functionality is the framework’s functionality related to Ajax calls to remote servers. The final example illustrates this:

<!doctype html>

<html ng-app="GoogleFinance">

<head>

<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js">

</script>

<script src="http://code.angularjs.org/1.0.6/angular-resource.js"></script>

<script>

angular.module('GoogleFinance', ['ngResource']);

function AppCtrl($scope, $resource) {

$scope.googleFinance = $resource('https://finance.google.com/finance/info',

{client:'ig', q: 'AAPL', callback:'JSON_CALLBACK'},

{get: {method:'JSONP', isArray: true}});

$scope.indexResult = $scope.googleFinance.get();

$scope.doSearch = function () {

$scope.indexResult = $scope.googleFinance.get({q: $scope.searchTerm});

};

}

</script>

</head>

<body>

<div ng-controller="AppCtrl">

<form class="form-horizontal">

<input type="text" ng-model="searchTerm">

<button class="btn" ng-click="doSearch()">

Search

</button>

</form>

Current Price: {{indexResult[0].l_cur}}<br/>

Change: {{indexResult[0].c}}<br/>

</div>

</body>

</html>

Angular resource is used to make the backend calls. The script that defines it needs to be included, and it needs to be referenced as a parameter in the controller. Because we are making a call to a site under a different domain, JSONP is specified as a method. The model (searchTerm) is used to specify a stock symbol to search for using the Google Finance API. The results are returned as a JSON array, and the current price and change fields are displayed upon retrieval.

These three examples are helpful for educational and demonstration purposes. They are stripped-down versions that highlight exactly what features are required and how they relate.

With a small amount of effort, Bootstrap’s stylesheet and some basic stylings can be added. Additional changes found in the code of this chapter add to the previous example by linking to the bootstrap.css, creating a container class and view rows, and adding a search icon and some other design adjustments. These all remain in a single self-contained file; a standard starter project breaks these resources up and organizes them in a standard directory structure.

These examples can be included in a starter project such as AngularJS seed or Bootstrap by adding relevant portions of the preceding code to the index page (or relevant included view). Ideally, inline JavaScript code presented in these examples is extracted into a separate file (to start: modules into app.js and controllers into controllers.js).

Conclusion

In any successful development team, each member has unique strengths that she brings to bear for the benefit of the project. The focus of one member allows others to pay closer attention in other areas, effectively limiting the problem scope under their attention. Starter projects and JavaScript frameworks insulate developers from details of BOM and DOM implementations, browser compatibility issues, initial concerns with code organization, and other challenges.

Hardware improvements and JavaScript performance optimization has made it possible to create large-scale JavaScript applications. Large-scale applications are much easier to manage when standard design is used, and project focus is enhanced by eliminating repetitive tasks required in every web development project. The frameworks introduced in this chapter are specific examples of projects that can jumpstart your next development effort and focus your team’s attention immediately on the functional concerns of your project.