The Web As Platform
Past, Present, and Future

Alex Russell <slightlyoff@google.com>
Twitter: @slightlylate
March 27, 2012

flickr.com/photos/stuckincustoms/3145980733

These Slides, Right Now:
Dev/Beta Channel Chrome
http://infrequently.org:8080/

The "Real Engineering" Critique of The Web

...you are technically correct — the BEST kind of correct.

Number 1.0, Futurama 2acv11

Web Platform Don't Care

flickr.com/photos/arnolouise/364315704
It's worth keeping in mind that none of the critiques you're leveling have mattered at all.

So Why Did It Succeed? What The Heck?

flickr.com/photos/11304375@N07/2252583074/

Where Is "Bottom", Anyway?

flickr.com/photos/kadenis/5121129043/

Virtually Non-Existent



It's Pain All The Way Down

flickr.com/photos/itkovian/2962467922/

What Do We Want In A Platform?

flickr.com/photos/11304375@N07/2769553173
If your answer to this sort of question is "type checking" or "performance", you're a very long way off the mark. What's *behind* those watchwords is what we're really after: * Security * Freedom to build things as large as our dreams * The ability to share those things as broadly as possible

The Platform Challenges

The Sun Rises,
Technology Sucks

What Did The Web Get Right?

Memetic Assets

The Humble <a>

flickr.com/photos/donsolo/3271552182/



en.wikipedia.org/wiki/Gestalt_psychology

The Other Side of Classes

// Classes are state with functions
function Behavior(config) {
  this.config = config;
  this.doIt = function(itemToActOn) {
    if (this.config.flag) {
      // ...
    } else {
      // ...
    }
  }
}

var b = new Behavior({ flag: false });
b.doIt($("item"));

The Other Side of Classes

// Closures are functions with state
function bindBehavior(config) {
  return function() {
    if (config.flag) {
      // ...
    } else {
      // ...
    }
  }
}

var b = bindBehavior({ flag: false });
b($("item"));
flickr.com/photos/evanblaser/5573908825

Network Economics Matter



HTTPArchive, 2012

http://www.flickr.com/photos/fimoculous/3210086353

A Platform's Apparent Level
of Abstraction Matters

flickr.com/photos/imh/3297961043/

Magic?




Throughout history
Every mystery
Ever solved has turned out to be
Not Magic.
Tim Minchin, Storm

Components Today

<script 
 src="http://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.xd.js">
</script>
<script>
dojo.require("dijit.dijit");
dojo.require("dijit.Calendar");

dojo.ready(function() {
    var c = new dijit.Calendar({
        value: new Date(),
        isDisabledDate: function(d) {
          // ...
        }
    });
    document.body.appendChild(c.domNode);
});
</script>

Web Components: Explaining The Magic

function Comment(text) {
  HTMLElement.call(this); // Makes this an Element
  this.textContent = text || '...';
  this.buildUI();
}

Comment.prototype = Object.create(HTMLElement.prototype);
Comment.prototype.constructor = Comment;
Comment.prototype.buildUI = function() { ... };
HTMLElement.register('x-comment', Comment);
var c = new Comment("Howdy, pardner!");
document.body.appendChild(c);
<!-- At risk in standards -->
<x-comment>...</x-comment>
<!-- Might instead be: -->
<div is="x-comment">...</div>

Shadow DOM

function Comment(text) {
  HTMLElement.call(this); // Makes this an Element
  this.textContent = text || '...';
  this.shadow = new ShadowRoot(this);
  this.buildUI();
}

Comment.prototype = Object.create(HTMLElement.prototype);
Comment.prototype.constructor = Comment;
Comment.prototype.buildUI = function() { ... };

HTMLElement.register('x-comment', Comment);

Declarative Matters

<element extends="div" name="greeting" constructor="Howdy">
  <script>
    this.lifecycle({
      created: function(shadowRoot) {
        shadowRoot.shadowHost.addEventHandler("click", function() {
              alert("And good day to you!");
            });
      }
    });
  </script>
  <template><h1>Hello World!</h1></template>
</element>
<div is="greeting"></div>
var c = new Greeting();
document.body.appendChild(c);

Data Binding: Model-Driven Views

<script> 
document.body.model = Model.get({
  'items': [
    { 'name': 'Africa',
      'children': [
        { 'name': 'Egypt' },
        { 'name': 'Kenya',
          'children': [ { 'name': 'Nairobi' }, { 'name': 'Mombasa' } ]
    } ] } ]
});
</script>
<template iterate="items" id="t"> 
  <li>{{name}}
    <ul><template ref="t" iterate="children"></template></ul> 
  </li> 
</template>

Imperative Primitives: Mutation Observers & Summaries

<script> 
var summary = new MutationSummary({
  callback: [function],         // required
  rootNode: [node],             // optional
  observeOwnChanges: [boolean], // optional
  queries: [{query}, …] // required. one query object at min.
});

// ...sometime later
summary.disconnect();
</script>

Dev/Beta Channel Chrome

http://infrequently.org:8080/

ES.next Modules

module widgets {
  module events from 'goog/events.js';
  import {EventType, FocusHandler, KeyHandler} from events;
  import * from 'goog/widget.js';

  export let collection = new WeakMap();
 
  export class DropDownButton extends Widget {
    constructor(attributes) {
      super(attributes);
      this.buildUI();
      // ...
    }
  }
}

Binary Data

const Point2D = new StructType({ x: uint32, y: uint32 });
const Color = new StructType({ r: uint8, g: uint8, b: uint8 });
const Pixel = new StructType({ point: Point2D, color: Color });
 
const Triangle = new ArrayType(Pixel, 3);
 
let t = new Triangle([{ point: { x:  0, y: 0 }, 
                        color: { r: 255, g: 255, b: 255 } },
                      { point: { x:  5, y: 5 }, 
                        color: { r: 128, g: 0,   b: 0   } },
                      { point: { x: 10, y: 0 }, 
                        color: { r: 0,   g: 0,   b: 128 } }]);

Maps & Iteration

let someObject = { name: "yet another anonymous object" };
let collection = new WeakMap();
collection.set(someObject, anotherObject);
collection.has(someObject) == true;
collection.get(someObject); // anotherObject
for (let [key, val] of items(someObject)) {
  // Look ma! I'm bound per iteration!
  doWork(val);
}

Classes Today

function Comment(text) {
  HTMLElement.call(this); // Makes this an Element
  ...
}

Comment.prototype = Object.create(HTMLElement.prototype);
Comment.prototype.constructor = Comment;
Comment.prototype.buildUI = function() { ... };

HTMLElement.register('x-comment', Comment);

Classes Today (For Real)

// Closure
goog.inherits(HTMLElement, Comment);

// Prototype
Comment = Class.create(HTMLElement, ... );

// MooTools
Comment = new Class({ extends: HTMLElement, ... });

// YUI
Comment = function () { Comment.superclass.constructor.call(this); }; 
YAHOO.lang.extend(Comment, HTMLElement);

// Dojo
dojo.define("Comment", [ HTMLElement ], ...);

// jQuery UI
$.widget( "comment", { ... });

ES.next Classes

class Comment extends HTMLElement {

  constructor(attrs = {}, ...args) {
    super(attrs);
    this.textContent = attrs.text || lorem;
    this.shadow = new ShadowRoot(this);
    this.buildUI(...args);
  }

  buildUI() { /*...*/ }

  css(...args) {
    super.css(...args);
    // Custom work here
  }
}

Thank you!
Questions?
Twitter: @slightlylate