Building Web Applications








Laurynas Veržukauskas
@Im0rtality

2014

Javascript


  • "just" Javascript
  • jQueryUI Widgets
  • + Templating
  • Databinding
  • Frameworks

  • AngularJS

Simple javascript

  • Writing 
      • fast short-term solutions
  • Debuging
      • easy (no library magic)
  • Maintenance
      • painful
  • OOP
      • in reality - none 
  • DOM manipulation
      • manual -> fragile

jQueryUI widgets

  • Writing 
      • somewhat faster
  • Debuging
      • somewhat harder
  • Maintenance
      • better, but still bad-ish
  • OOP
      • objects
  • DOM manipulation
      • manual -> fragile

+ Templating (1/2)


Use templates to generate HTML
Still manual injection to DOM

  • dust.js (by LinkedIn)
  • Hogan.js (by Twitter)
  • Mustache.js
  • pure.js
  • Handlebars.js

+ Templating (2/2)

  • Writing 
      • faster
  • Debuging
      • easier
  • Maintenance
      • even better
  • OOP
      • objects, views
  • DOM manipulation
      • semi-auto -> fragile

+ Databinding (1/3)

  • Ractive.js
  • Rivets.js
  • Epoxy.js (for Backbone) 
  • Knockout.js

No more DOM manipulation by hand!*


* - Unless we want it explicitly

+ Databinding (2/3)

  • Writing 
      • same
  • Debuging
      • easier
  • Maintenance
      • even better again
  • OOP
      • objects, views, models
  • DOM manipulation
      • auto -> NOT fragile

+Databinding (3/3)

Problems

  • Philosophy is VERY different from jQuery
    • view <-> data separation
    • test driven development
    • jQuery becomes obsolete

Frameworks (1/3)

Model-View-Whatever
Objects + Templating + Databinding
One package

  • AngularJS (by Google)
  • Backbone
  • Ember.js

Frameworks (2/3)

  • Writing 
      • faster (less boilerplate)
  • Debuging
      • easier (decoupled code)
  • Maintenance
      • easier (highly testable)
  • OOP
      • views,  models, controllers,  services
  • DOM manipulation
      • auto -> NOT fragile

Frameworks (3/3)

Problems

  • Learning curve
  • jQuery philosophy difference (inherits)


What to choose?

  • Backbone - DIY framework, lot of boilerplate
  • Angular - structured, short, clean, mocks, DI, easiest start
  • Ember - includes a LOT of utils, enforces specific structure

  • Initial release back in 2009
  • MV* framework
  • Huge community (StackOverflow 74k questions)
  • jQuery not even required
  • Actively developed
  • Clean code
  • Testable
  • IE 8+

How it came to be

  • Miško Hevery's bet with manager
  • Goole Feedback
    • 17k LOC -> 3 weeks -> 1,5k LOC

Objectives

  • Decoupling (DOM <-> Logic)
  • Decoupling (Frontend <-> Backend)
  • Testability

Built with

  • Youtube on PS3 (by Google)
  • Plunker
  • VEVO
  • DoubleClick (by Google)
  • ...

index.html

<!doctype html>
<html lang="en" ng-app="myApp">
<head>
  <meta charset="utf-8">
  <title>My AngularJS App</title>
  <link rel="stylesheet" href="css/app.css"/>
</head>
<body>
  <ul class="menu">
    <li><a href="#/view1">view1</a></li>
    <li><a href="#/view2">view2</a></li>
  </ul>

  <div ng-view></div>

  <script src="lib/angular/angular.js"></script>
  <script src="lib/angular/angular-route.js"></script>
  <script src="js/app.js"></script>
  <script src="js/controllers.js"></script>
</body>
</html>

app.js

'use strict';

angular.module('myApp', [
   'ngRoute',
   'myApp.controllers'
])
.config(['$routeProvider', function($routeProvider) {
  $routeProvider
.when('/view1', {
templateUrl: 'partials/partial1.html', 
controller: 'MyCtrl1'
})
.when('/view2', {
  templateUrl: 'partials/partial2.html', 
  controller: 'MyCtrl2'
})
.otherwise({redirectTo: '/view1'});
}]);

controllers.js

'use strict';

angular.module('myApp.controllers', [])
.controller('MyCtrl1', [function() {
}])
.controller('MyCtrl2', [function($scope) {
$scope.messages = [
{from: 'batman', body: 'nana nana nana nana batman!'},
{from: 'joker', body: 'why so serious?'}
];
}]);

partial1.html


<p>This is the partial for view 1.</p>



partial2.html



<p ng-repeat="message in messages">
  {{ message.from }}: {{ message.body }}
</p>

filters.js


'use strict';
angular.module('myApp.filters', [])
.filter('strlen', [function() {
    return function(text) {
      return String(text).length;
    }
}]);

  partial2.html



<p ng-repeat="message in messages">
  {{ message.from }}:[ {{ message.body | strlen }} characters]
</p>


  • Unit Testing
  • Midway Testing
  • E2E Testing

filtersSpec.js

'use strict';

describe('filter', function() {
  beforeEach(module('myApp.filters'));

  describe('strlen', function() {

    it('should get string length',

inject(function(strlenFilter) {
      expect(strlenFilter('nana')).toEqual(4);
     })
);
  });
});

scenarios.js

'use strict';

describe('my app', function() {
  browser.get('index.html');
  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {
    expect(browser.getLocationAbsUrl()).toMatch("/view1");
  });

  describe('view1', function() {
    beforeEach(function() {
      browser.get('index.html#/view1');
    });
    it('should render view1 when user navigates to /view1',
function() {
       expect(element.all(by.css('[ng-view] p'))
.first().getText()
)
.toMatch(/partial for view 1/);
    });
  });

Gotchas

  • Organize your files
  • Lazy-load your code
  • Serialize application state to the URL
  • Derive application state from the URL
  • Manage a Model layer
  • Do smart caching
  • Work with a RESTful interface (for real)
  • Use a 3rd-party lib with Angular

Resources







Questions?

Building Web Applications

By Laurynas Veržukauskas