Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

your stuff runs on both sides

@olympum #mojito JSConfUS 2012

broken things

(yes, we are all broken)

always, always, always assume that JavaScript may not run on the client, because that's exactly what will happen.

NoJSConf

why?

networks

packet loss is a reality, especially in emerging countries

assume connected devices are only partially connected

spotty reachability is common on mobile networks

latency is not constant, 100kb are not 10*10kb

mobile

almost 6b mobile subscribers worldwide in 2011

277m mobile Internet users in China, 66% of Internet users

mobile web !== desktop web. mobile devices are only partially connected

not just latency limitations: battery life, bandwidth, processor, memory ...

never, ever, ever assume JavaScript will be available nor fully capable in the client device

do the right thing
progressive enhancement
progressive enhancement should be the easiest path of development, it should not need to be harder!
the Wall between client and server makes progressive enhancement the hardest path of development
our friend the hyper-link
            
<a href="/posts" id="mylink">all posts</a>
            
        
server-side resource controller
            
  def index
    @posts = Post.all
  end
            
        
server-side template
            
<div id="posts">
<h1>Listing posts</h1>
 
<ul>
<% @posts.each do |post| %>
    <li><a href="/posts/<%= post.id %>"><%= post.title %></a></li>
<% end %>
</ul>
</div>
            
        
a list of hyper-links
            
<div id="posts">
<h1>Listing posts</h1>
 
<ul>
    <li><a href="/posts/1">my first post</a></li>
    <li><a href="/posts/2">my second post</a></li>
</ul>
</div>
            
        
JavaScript handler

var handleClick = function(e) { 
    Y.io('/posts', {
        on: {
            complete: function (id, response) {
                // update #posts inner html
            }
        }
    });
}
Y.on("click", handleClick, "mylink");
        
server-side handler
            
  def index
    @posts = Post.all
    respond_to do |format|
      format.html  # index.html.erb
      format.json  { render :json => @posts }
    end
  end
            
        
code duplication

faced with duplication

developers implement only AJAX

and because networks can break

pages will break

we must remove duplication

fight duplication: server-side JavaScript to the rescue

we need to make client-side JavaScript and server-side JavaScript be equivalent

luckily YUI3 does the lion's share of the work

how?

browser

DOM

JS

client stuff

Node.JS

http

JS (V8)

server stuff

JavaScript (DOM/strings)

PHP (strings/DOM)

HTTP (strings)

more than server-side JavaScript:

serialization matters, we are all bits

☛ a server-side DOM does not solve the serialization

☛ stringify-friendly data serialization format, aka JSON

☛ memory efficient data transform via templates

☛ isolate DOM access to binders

bring the server to the client

☛ leverage the client's storage and CPU

☛ confine expensive DOM operations to the client

☛ optimize the server for operating with "bits"

☛ fallback on the server when the client won't

the device is in the cloud
mojit

model

YUI.add('galleryModelFlickr', function(Y) {
// register model in Y.mojito.models namespace.
Y.namespace('mojito.models').gallery = {
    get_photos: function(callback){
      Y.YQL (flickr_query, function(rawYql) {
        if (null == rawYql || 0 == rawYql.query.count) {
          callback ([]);
        } else {
          callback(rawYql.query.results);
        }
      }
    };
}, '0.0.1', {requires: ['yql']});

view

<div>
    <p>The user is from {{country}}.</p>
</div>

index.opera-mini.mu.html
index.iphone.mu.html
index.ipad.mu.html
...

controller

YUI.add('flickr', function(Y) {
  Y.mojito.controller = {
    index: function(ac) {
      var gallery = ac.models.gallery;
      gallery.get_photos (function(photos) {
        ac.done (
          {
            ac.done(photos);
          }
        )'
      });
    }
  };
}, '0.0.1', {requires: []});

ActionContext API

ac.models.*.getData();
ac.config.get('key');
ac.params.body('key');
ac.assets.addCss('./style.css');
ac.cookie.set('flavor', 'choco-chip');
ac.http.addHeader('x-foo', 'val');
ac.done('a string');
ac.error('oops');

mojit library

dispatch

client

DOM

Binders

Proxy

server

http

Node.JS

Express

spread the news

☛ 100% JavaScript & one codebase

☛ your stuff runs on both sides

☛ progressive enhancement, no excuses

a mouthfull

☛ partially-connected JavaScript real-time data peers

mixology at the mojito bar

free t-shirt, free mojitos - open today & tomorrow

talk to y! developers, give mojito a try!

bonus cocktails: grasshopper & manhattan

shaker talk tomorrow by Julien Lecomte

Use a spacebar or arrow keys to navigate