Google Developers Live IL

Who is this Guy?

Agenda

  • Mobile App Engine Backends
  • Defining the modern web app
  • HTML5 Power tools/APIs
  • DevTools Tips

Google App Engine

Quick Introduction

What is Google App Engine?

Easy to build

Easy to scale

Easy to maintain

Google App Engine

Google App Engine passed 7.5B+ daily hits

Core Features



Storage



Datastore, Cloud SQL,
Memcache


Compute



Frontends, Backends,
Task Queues, Cron


Services



Users, Mail, Images,
UrlFetch, MapReduce,
TrafficSplitting, Search

Month in the life of Google App Engine:


1,000,000 active applications

2 Trillion datastore operations

half of active world IP addresses touch GAE

Storage

  • Fully managed NoSQL solution
  • Built for scale (size and traffic)
    • 2 Trillion operations per month
  • Same technology we use for our own applications
  • Provisioning? Sharding? Scaling? It just works
    • Automatically splits and balances data
      based on load
  • Not reliant on a single datacenter
  • Handles local issues and catastrophic failures
openclipart.org/detail/16266/multiple-files-by-johnny_automatic-16266
Getaround

Creating your own APIs

Motivation

So you wanna build an app

...so it has to work on multiple platforms

So you wanna build an app

...so it has to scale

So you come up with a design

And you start to implement your design

And then you write your client side code

And then you launch

What are you doing?

What are you doing?

Introducing Google Cloud Endpoints

Using Google APIs

How could this possibly be related?

Discovery Document

Service Objects

gapi.client.load('urlshortener','v1',function(){});
fromapiclient.discovery import build
service =build('urlshortener','v1')
Other languages supported:
  • Java
  • Objective C
  • PHP
  • .NET
  • Go
  • Ruby
  • ...

Creating your own APIs

Using Google Cloud Endpoints

Tic Tac Overview

  • Write your backend code
  • Decorate API methods
  • Generate client libraries
  • Write client apps

Let's play

https://cloud-endpoints-roadshow.appspot.com/tictactoe

Who else is playing?

The API is!

Let's play

What about mobile?

  • iOS
  • Android

API Explorer

The Power Of HTML5
+
Native & Desktop Experiences
Modern Web Apps

Modern web app

  • Self Contained & Functional
  • "Offline First"
  • Client Side Architecture
  • Device Aware
  • 60fps
examples for great web apps that leverage html5 apis

Client Side Frameworks

  • Angular.js - AngularJS lets you extend HTML vocabulary for your application
  • Backbone.js - Gives structure to web applications by providing models with binding, collections and views
  • Ember.js - Don't waste time making trivial choices
todomvc project

...And on the server side:
Google Cloud End Points: bit.ly/gce-web - Full Tutorial
Endpoints Proto Datastore API

Offline - Why?

  • Better performance
  • Airplane, road trip, deserted island
  • Flaky connections (e.g. cafes, car)
  • Consolidates the concept of permanent app
    you will have always available
offline on the road

Offline - How?

  • Storing assets: AppCache
  • Storing data: localStorage, IndexedDB , File API.
  • Offline first:
    • Pretend that there's no internet connection
    • Implement a sync layer that works only when online.
  • navigator.onLine & window.(ononline|onoffline)
offline on the road

HTML5 Cool APIs

CSS For Web Apps

Confirmed

Floats, Tables, & Positioning... Balagan!

  • Floats stack horizontally to allow simple placement.
  • Tables lack repeatability and semantic meaning.
  • Using absolute positioning is difficult. Makes adaptive display hard.
  • CSS3 specifications address layout cases with regions, exclusions, grid and flexible box .

2012: The Rise of CSS for Web Apps

Achieve That "Holy Grail" Layout!

Alignment

Vertically centered content is easy peasy!

.box {
  display: ;
  : ;
  : ;
 }
A
B
C

Ordering & Orientation

Order independent from source

  • Content is laid out from lowest to highest numbered ordinal group.
  • Items with the same order group are laid out per source document.
.box {
  : ;
}
.box > :nth-child(2) {
  : ;
}
A
B
C

Flexibility

  • Flexbox items alter their width/height to fill available space.
  • Items grow/shrink proportional to their positive/negative flexibility
  • 3rd argument is preferred size
.box > * {
  : 1 0 0px;
}
.box > :nth-child(2) {
  :   px;
}
A
B
C

Browser Support

CSS Flexbox ( da new one )

Dynamic CSS

Confirmed

calc()

.circle {
  width: 300px;
  height: 300px;
}
div {
  display: ;
  width: (100% - 4em);
  height: (100% - 4em);
  border-radius: 50%;
  : center;
  : center;
}
div:hover {
  border-radius: 0;
}

Browser Support

CSS calc()

Old Hat for JS Frameworks

Angular ( angularjs.org ) example:

  <div ng-app ng-init="val=25">
    Volume: <input type="range" min="0" max="100" ng-model="val">
    {{val}}/100
  </div>
Volume: {{val}}/100

One-way Data Binding: data-* Attributes

"Poor man's data binding"

  • Model: data attribute
  • Use attr() to get the value(s)
  • View: render generated content to :before / :after pseudo elements
  • Hook listeners that watch for changes.

"Poor Man's Data Binding"

<style>
input::after {
  content: attr(data-value) '/' attr(max);
  position: relative;
  left: 135px; top: -20px;
}
</style>
<input type="range" min="0" max="100" value="25">
<script>
var input = document.querySelector('input');
input.dataset.value = input.value; // Set an initial value.

input.addEventListener('change', function(e) {
  this.dataset.value = this.value;
});
</script>
Volume:

One-way Data Binding: <datalist>

Browsers: <input list="browsers">
<datalist id="browsers">
  <option value="Chrome">
  <option value="Firefox">
  <option value="Internet Explorer">
  <option value="Opera">
  <option value="Safari">
</datalist>
  • Specifies a list of pre-defined options for an <input> element.
  • list attribute "binds" data list to an <input>
  • Useful for "autocomplete" on <input> elements.

Browsers:

Browser Support

Data binding with data-* attrs / <datalist>

Multithreaded Programs

Confirmed

I Got So Excited... I Wrote a Book :)

Web Workers

index.html

function startWorker(settings) {
  var myWorker = new Worker('scripts/worker.js');
  myWorker.addEventListener("message", workerListener, false);
  myWorker.postMessage(settings);
}          
       

Worker.js

self.addEventListener('message', function(e) {
  doSomeWork();
};
function doSomeWork() {
  importScripts('http://url?callBack=handleWork');
}
function handleWork() {
  postMessage(result);
}
     

Web Worker - Debug

Access a Filesystem

Confirmed

HTML5 Filesystem API

Persist data to files/folders

Opening a filesystem:

window.(
  TEMPORARY,        // persistent vs. temporary storage
  1024 * 1024,      // size (bytes) of needed space
  initFs,           // success callback
  opt_errorHandler  // opt. error callback, denial of access
);
  • Security: sandboxed per origin
  • Power: native apps can do files/folders,...web apps should too!
  • Benefit: dynamically cache and manage assets.

Using Local Assets

  • Stored files/folders get their own ( filesystem: ) URL:
filesystem:http://example.com/temporary/image.png
  • Use for a src/href value:
var img = document.createElement('img');
img.src = fileEntry.toURL();
document.body.appendChild(img);
  • Get back to a FileEntry from its filesystem: URL:
window.(img.src, function(fileEntry) { ... });

filer.js ( github.com/ebidel/filer.js )

Wrapper lib that implements common UNIX cmds (ls, cp, mv)

var filer = new Filer();

filer.init({persistent: false, size: 1024 * 1024}, function(fs) {...}, onError);

filer.ls('path/to/some/dir/', function(entries) { ... }, onError);

filer.cp('file.txt', '/path/to/folder', 'newname.txt', function(entry) {
  // entry.fullPath == '/path/to/folder/newname.txt'
}, onError);

var b = new Blob(['body { color: red; }'], {type: 'text/css'});
filer.write('styles.css', {data: b, type: b.type}, function(entry, writer) {
    ...
}, onError);

But kind Sir, this marvel is only in Chrome!

Oh yeah?

Browser Support

HTML5 Filesystem API - thanks to idb.filesystem.js shim!

Evolution of postMessage()

3. Complex types ( File , Blob , ArrayBuffer ) via structured cloning

var data = [1, 2, 3, 4];

// Blob() in Chrome 20, FF 13
worker.postMessage(new Blob(data.toString(), {type: 'text/plain'}));

var uint8Array = new Uint8Array(data);
worker.postMessage(uint8Array);
worker.postMessage(uint8Array.buffer);
  • Problem: all of these methods are copies. Not efficient!
  • We can do better...

Transferable Objects

a.k.a. workers that "don't suck"

Same old friend, different semantics (note the vendor prefix):

worker.(arrayBuffer, [arrayBuffer]);
window.(arrayBuffer, targetOrigin, [arrayBuffer]);
  • Zero-copy
    • Ownership of data ( ArrayBuffer ) is transferred to new context (e.g. worker/window). Source buffer becomes unavailable.
    • ~50x faster than structured cloning (Chrome 13/FF).
  • 2nd argument is list of what to transfer.

Demo: Transferable Objects

Feature Detection

  • Feature detecting is a PITA b/c of false positives.
  • If transferred, buffer's .byteLength goes to zero.
var ab = new ArrayBuffer(1);
worker.(ab, [ab]);
if (ab.byteLength) {
  alert('Transferables are not supported in your browser!');
} else {
  // Transferables are supported.
  // PITA = pain in the...
}

Browser Support

Transferable Objects

"Device APIs"

Device APIs WG: www.w3.org/2009/dap/

  • Geolocation API (Psst... support in DevTools)
  • Device Orientation API ( accelerometer in your DevTools)
  • WebGL ( GPU )
  • HTML5 Filesystem API ( sandboxed filesystem )
  • navigator.onLine / navigator.connection ( network connectivity )
  • Battery API
  • Gamepad API
  • WebRTC ( voice & video input ) / Web Audio API ( core audio )

First Step to Speech Enabled Apps!

<input type="text" x-webkit-speech> 

Camera & Microphone Access

Plugin-free acess to camera/microphone.

navigator.({audio: true, video: true}, function(stream) {
  var video = document.querySelector('video');
  video.src = window.(stream);
}, function(e) {
  console.log(e);
});
<video autoplay controls></video>

WebRTC Demos

Recording Content

<input type="button" value="⚫" onclick="record(this)">
<input type="button" value="◼" onclick="stop(this)">
var localMediaStream, recorder;

var record = function(button) {
  recorder = localMediaStream.record();
};

var stop = function(button) {
  localMediaStream.stop();
  recorder.getRecordedData(function(blob) {
    // Upload blob using XHR2.
  });
};

Browser Support

getUserMedia()

Binary WebSockets

New look, same great taste

  • WebSockets suffered the same limitations as Workers.
  • Now send File , Blob , or ArrayBuffer types.
var socket = new WebSocket('ws://example.com/sock', ['dumby-protocol']);
socket.binaryType = 'blob'; // or 'arraybuffer'
socket.onopen = function(e) {
  window.setInterval(function() {
    if (socket.bufferedAmount == 0) {
      socket.send(new Blob([blob1, blob2]));
    }
  }, 50); // rate limit us.
};
socket.onmessage = function(e) {
  document.querySelector('img').src = (e.data);
};

Chrome Frame

Meta tag:

<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
                

Header:

X-UA-Compatible: IE=Edge,chrome=1

*Bold* Audio Demos

The Web Can Do Amazing Things...

    But it is just the beginning!

    The Web

    Is What You Make Out Of It

    Resources