If you have fast machine and recent Google Chrome or Safari installed, please check a bit more "moving" version of that presentation

Otherwise, scroll down to see the slides

Fast web applications

Backed with Node.js

Mariusz Nowak

github.com/medikoo

JavaScript programmer at

The less you do on the server The more clients you can serve

At Roche we recently delivered HTML5 application

Client-side code statistics

303 modules from 19 packages

13 thousand lines long and weights about 450kB

219kB when minified

60kB when minified and gzipped

One average picture on Facebook weights 100-500kB (depends on screen resolution)

How is it built?

Code organization

CommonJS (NodeJS) modules

add.js

module.exports = function() {
  var sum = 0, i = 0, args = arguments, l = args.length;
  while (i < l) sum += args[i++];
  return sum;
};

increment.js

var add = require('./add');
module.exports = function(val) {
  return add(val, 1);
};

program.js

var inc = require('./increment');
var a = 1;
inc(a); // 2

Bundled for browser with modules-webmake

(function (modules) {
  // about 60 lines of import/export path resolution logic
})({
  "root": {
    "add.js": function (exports, module, require) {
      module.exports = function () {
        var sum = 0, i = 0, args = arguments, l = args.length;
        while (i < l) sum += args[i++];
        return sum;
      };
    },
    "increment.js": function (exports, module, require) {
      var add = require('./add');
      module.exports = function (val) {
        return add(val, 1);
      };
    },
    "program.js": function (exports, module, require) {
      var inc = require('./increment');
      var a = 1;
      inc(a); // 2
    }
  }
})("root/program");

More information in

JavaScript Modules Done Right

Data storage

Simple key/value pairs

mongodb on a server

localStorage on a client

Data manipulation

Evented database engine in JavaScript

var nsdoctor = db.create('doctor', {
  name: { type: 'text', label: 'Name', required: true },
  email: { type: 'email', label: 'E-mail', required: true }
});
var nspatient = db.create('patient', {
  name: { type: 'text', label: 'Name', required: true },
  doctor: { type: nsdoctor, label: 'Doctor', required: true }
});
var nsvisit = db.create('visit', {
  doctor: { type: nsdoctor, label: 'Doctor', required: true },
  patient: { type: nspatient, label: 'Patient', required: true },
  date: { type: 'datetime', label: 'Date', required: true }
});

Objects

var john = nsdoctor.create({ name: 'John Smith', email: 'john.smith@roche.com' });
// Meta:
john._id // globally unique  np. 'fsay6u234sd'
john._created // creation date
john._updated // modification date
// Visible object properties (possible only with ECMAScript5)
Object.keys(john) // ['name', 'email']

Collections of given type (namespaces)

// Unordered (hash objects)
// All visible properties are object instances:
nsdoctor // { fsay6u234sd: john }
Object.keys(nsdoctor) // ['fsay6u234sd']

var ian = nspatient.create({ name: 'Ian Tate', doctor: john });
var henry = nspatient.create({ name: 'Henry Wilkinson', doctor: john });

ian._id // 'gdsaa78sdf'
henry._id // '5rgrs23bfe'
Object.keys(nspatient) // ['gdsaa78sdf', '5rgrs23bfe']

Relations

var johnPatients = john._get(nspatient);
// Unordered
Object.keys(docPatients); // ['gdsaa78sdf', '5rgrs23bfe']

var carol = nspatient.create({ name: 'Carol Hanson', doctor: john });
carol._id // 'yuerert435'

// All data relations are updated realtime
Object.keys(johnPatients); // ['gdsaa78sdf', '5rgrs23bfe', 'yuerert435']

Ordered lists

var plist = nspatient.list('name');
plist // [carol, henry, ian]

// Updated in next event-loop
henry._set('name', 'Zahary Wilkinson');
setTimeout(function () {
  plist // [carol, ian, henry]
}, 0);

Filters

var flist = nspatient.filter('name', function (name, obj) {
  return name.indexOf('Ian') === 0;
});
Object.keys(flist) // ['gdsaa78sdf']

// Updated realtime
henry._set('name', 'Ian Wilkinson');
Object.keys(flist) // ['gdsaa78sdf', '5rgrs23bfe']

// We can created ordered lists from filters
flist.list('name') // [ian, henry]

Synchronization & Conflicts

No conflict resolution. Latest update wins

Templates

Engine: domjs

header(
  h1('Heading'),
  h2('Subheading'));

  nav(
    ul({ 'class': 'breadcrumbs' },
      li(a({ href: '/' }, 'Home')),
      li(a({ href: '/section/'}, 'Section')),
      li(a('Subject'))));

  article(
    p('Lorem ipsum...'));

  footer('Footer stuff');

Construction doesn't have to be linear

var myul = ul(li('one'), li('two'), li('three'));
p("Lorem ipsum...");
// Add extra items to list
myul(li('four'), li('five'));
// Move list to other element
div(myul);

Views & Routing

Single-page application with regular links and urls

Browser history is handled with HTML5 History

Link clicks are hijacked and view changes are invoked

Views are defined by describing differences from parent view

// |-> Home
//   |-> Profile
//   |-> Patients
//     |-> Patient
//       |-> Add visit
//   |-> Visits
//     |-> Visit

var home     = view('home.tpl');
var profile  = home.diff('profile.tpl');
var patients = home.diff('patients.tpl');
var patient  = patients.diff('patient.tpl');
var addVisit = patient.diff('add-visit.tpl');
var visits   = home.diff('visits.tpl');
var visit    = visits.diff('visit.tpl');

Other modules

SocketIO

Handles client/server socket connections

Formidable

Handles asynchronous files uploads on server side

Forever

Keeps production server process running

Nodemailer

Sends email notifications

JSLint

Code quality guard

node-mongodb

MongoDB driver for Node.js

TAD

Test suite

Low level modules

es5-ext

Extensions to EcmaScript5 API

deferred

Aid for asynchronous programming

For more info see Asynchronous JavaScript slides

event-emitter

Simple cross-environment event emitter interface

Browsers support

EcmaScript 5 application

Firefox 4+, Chrome 13+, Safari 5+, IE10+

IE9 can be supported in very limited way

(no Offline and no History)

What about EcmaScript 3 engines?

With same code we can serve static pages using NodeJS server

Trend is growing

Questions?

Thank you !

Mariusz Nowak

github.com/medikoo

Use a spacebar or arrow keys to navigate