Mobile Webapps
Matteo Antony Mistretta
Let's get serious

- Client
- Server
- Both (isomorphic)
- Native (universal apps)
- Embedded (Johnny-Five)
Node
Single-threaded, event-driven, scalable
var http = require('http');
var server = http.createServer(function (req, res) {
res.end('<html><body><h1>Hello world!</h1></body></html>');
});
server.on('/about', function(req, res) {
if (req.method === 'GET') {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('We are young');
res.write('We are strong');
res.write('We’re not looking for where we belong');
res.end();
}
});
server.listen(3000, '127.0.0.1');
console.log('Server running at http://127.0.0.1:3000/');NPM
npm init
npm install --save lodash
npm install --save-dev uglifyjs
npm update --save
npm update --save-dev
npm install -g coffee-script
npm list -g --depth=0
npm install
npm test
npm start
npm run uglifyvar _ = require('lodash');
function weightedAverage(marks, weights) {
var squares = _.map(marks, function(mark, index) { return mark * weights[index] });
var weightedAvg = _.reduce(squares, function(prev, curr) { return prev + curr });
return weightedAvg / _.reduce(weights, function(prev, curr) { return prev + curr });
}
module.exports = { weightedAverage: weightedAverage };
Bower
bower init
bower install --save jquery
bower install --save git://github.com/user/package.git
bower install --save http://example.com/script.js
bower update --save
bower install<!DOCTYPE html>
<html>
<head>
<script src="/lib/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-2.2.1.min.js"></script>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
</head>
<body>
<div id="app">
<p>Awesome!</p>
</div>
</body>
</html>Express
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.post('/', function (req, res) {
res.send('Got a POST request');
});
// middlewares
app.use(express.static(__dirname + '/bower_components'));
app.use(express.static(__dirname + '/public'));
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Preprocessors
Because JavaScript just isn't enough for us

Reasons to learn them
- Sugar syntax
- More power
- Live the future
- Keep up the pace
TypeScript
/// <reference path="phaser.d.ts" />
window.onload = function() {
var game: Phaser.Game,
platforms: Phaser.Group,
player: Phaser.Sprite,
cursors: Phaser.CursorKeys,
score: number,
scoreText: Phaser.Text;
game = new Phaser.Game(
800, 600, Phaser.AUTO, '',
{
preload: preload,
create: create,
update: update
}
);
function preload() { }
function create() { }
function update() { }
};/// <reference path="phaser.d.ts" />
window.onload = function() {
var game, platforms, player,
cursors, score, scoreText;
game = new Phaser.Game(
800, 600, Phaser.AUTO, '',
{
preload: preload,
create: create,
update: update
}
);
function preload() { }
function create() { }
function update() { }
};
ES6
const {Object3D, Material} = Core;
class Mesh extends Object3D {
constructor(
geometry = new Geometry(),
material = new Material({
color: 0xffffff
})
) {
super();
this.geometry = geometry;
this.material = material;
this.updateMorphTargets();
}
}... you don't want to know.Module systems
Let's try to avoid global namespace pollution

Namespace pattern
AKA "One namespace to rule them all"
//------ lib.js ------
(function(root) {
(function(app) {
var myPrivateVar;
function MyModule() {
...
}
root.app.MyModule = MyModule;
})(root.MyApp || (root.MyApp || {}));
})(MyCompany || (MyCompany = {}));
//------ main.js ------
(function() {
var lib = new MyCompany.MyApp.MyModule();
})();CommonJS
//------ lib.js ------
var math = require('awesome-math-library');
var square = function(x) {
return x * x;
};
module.exports = {
diag: function(x, y) {
return math.sqrt(square(x) + square(y));
}
};
//------ main.js ------
var lib = require('./lib');
console.log(lib.diag(4, 3)); // 5The Node/NPM way
AMD
//------ lib.js ------
define(['awesome-math-library'], function(math) {
var square = function(x) { return x * x; };
return {
diag: function(x, y) {
return math.sqrt(square(x) + square(y));
}
};
});
//------ main.js ------
requirejs.config({
baseUrl: 'scripts',
paths: {
'awesome-math-library': '../vendor/math.min'
},
shims: { 'backbone': { deps: ['underscore'], exports: 'Backbone' } }
});
define(['./lib'], function(lib) {
console.log(lib.diag(4, 3)); // 5
});Kindly brought to you by RequireJS
UMD
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
define(['dep1', 'dep2'], factory);
}
else if (typeof module === 'object' && module.exports) {
module.exports = factory(require('dep1'), require('dep2'));
}
else {
root.MyGlobalModule = factory(root.GlobalDep1, root.globalDep2);
}
}(this, function(Dep1, dep2) {
return {
combine: function() {
return new Dep1().awesomeFunc(dep2);
}
};
}));Be friends with everyone :)
ES6 imports
// lib.js
import {obj1, obj2} from 'dep1';
import dep2 from 'dep2';
export const PI = 3.14;
export function square(x) {
return x * x;
}
export default MyLib = {
hello: 'world'
}
// main.js
import {PI, square}, MyLib from 'lib';Peace, at last.
War is not over yet
Automation Tools
Repetitive tasks belong to machines

Build: Gulp


Build: Grunt
Scaffolding: Yeoman

Tests
-
BDD: Jasmine
-
Cross-browser: Karma
-
E2E: Protractor
Frameworks
Backbone
MVC? MVVM!

AngularJS
A quick recap
angular.module('todosApp', ['ngRoute', 'todosCtrl','todosFlt', 'todosSvc']);
var todosCtl = angular.module('todosCtl', []);
todosCtl.controller('TodoListCtl', ['$scope', 'Todo', function($scope, Todo) {
$scope.todos = Todos.query();
$scope.orderProp = 'age';
}]);
var todosSvc = angular.module('todosSvc', ['ngResource']);
todosSvc.factory('Todo', ['$resource', function($resource){
return $resource('todos/:id.json', {}, {
query: {method:'GET', params: {id: 'todos'}, isArray:true}
});
}]);<ul ng-controller="TodoListCtl">
<li ng-repeat="todo in todos | orderBy:orderProp">
<input type="checkbox" ng-model="todo.completed">
<label ng-class="{completed: todo.completed}">{{todo.title}}</label>
<button class="destroy" ng-click="removeTodo(todo)"></button>
</li>
</ul>ui-router, restangular, ui-bootstrap, ...
Angular2 (1/2)
The future is now. Welcome to Java 5
export class Todo {
completed: Boolean;
private _title: String;
get title() { return this._title; }
set title(value: String) { this._title = value.trim(); }
constructor(title: String) { this.completed = false; this.title = title; }
}
import {Component} from 'angular2/core';
import {TodoStore, Todo} from './services/store';
@Component({
selector: 'todo-app',
templateUrl: 'app/app.html'
})
export default class TodoApp {
todoStore: TodoStore;
constructor(todoStore: TodoStore) { this.todoStore = todoStore; }
remove(todo: Todo) { this.todoStore.remove(todo); }
}
Angular2 (2/2)
"Wow, it's so readable!" - Perl developer
<ul class="todo-list">
<li *ngFor="#todo of todoStore.todos"
[class.completed]="todo.completed">
<input type="checkbox"
(click)="toggleCompletion(todo)"
[checked]="todo.completed">
<label>{{todo.title}}</label>
<button (click)="remove(todo)"></button>
</li>
</ul>
<input [(ngModel)]="todo.title">import {bootstrap} from 'angular2/platform/browser';
import TodoApp from './app'
import {TodoStore} from './services/store';
bootstrap(TodoApp, [TodoStore]);React
Declarative, reactive, functional, performant
var KnockKnock = React.createClass({
// mixins: [StopUsingMe],
getInitialState: function() { return { sound: this.props.sound } },
render: function() { return <div>{this.props.sound} {this.state.sound}</div> }
});
class Hello extends React.Component { // v0.14
constructor(props) {
super(props);
this.state = { who: props.who };
}
render() { return <div>{this.props.greeting} {this.state.who}</div> }
}
const Goodbye = ({words}) => {
return <ul>{words.map(word => <li key={word}>{word}</li>)}</ul>
}
ReactDOM.render(
<div>
<KnockKnock sound={'knock'} />
<Hello greeting={'hello'} who={'world'} />
<Goodbye words={['goodbye', 'cruel', 'world']} />
</div>,
document.getElementById('container'))Flux Architecture: Redux
It's 'state machines', not 'transition machines'



react-redux
Your personal time machine
- Presentational/Container components
- Decorator vs. Mixins
- connect, Provider

Performance tips

KISS

Rules of optimization
Coding Tricks
- Write JavaScript-y code
- Use local variables, avoid globals
- Attach methods to prototype
- Use immutability
- Minimize DOM touches
- Minimize APIs server-side
- Don't reinvent the wheel
- DRY
- Prefer readability over performance
Google PageSpeed Rules
Travel Light
- Is SPA necessary?
- Are all browsers necessary?
- Is all JS necessary?
- Is all CSS necessary?
- Are all those HTTP requests necessary?
- Is client-only necessary?
Thank you!
Matteo Antony Mistretta
Github: IceOnFire, IngloriousCoderz
LinkedIn: antonymistretta
Twitter: antonymistretta
Email: antony.mistretta@gmail.com

Mobile webapps
By Matteo Antony Mistretta
Mobile webapps
- 576