62
Javascript Application Architecture with Min Ming Lo [email protected] | @lominming

Javascript Application Architecture with Backbone.JS

Embed Size (px)

DESCRIPTION

Intro to Javascript Application Architecture with Backbone.JS. Overview on Javascript MVC, templating with Underscore.js, and Single-Page Apps.

Citation preview

Page 1: Javascript Application Architecture with Backbone.JS

Javascript Application Architecture with

Min Ming Lo [email protected] | @lominming

Page 2: Javascript Application Architecture with Backbone.JS

Agenda

•  Intro

•  What is Backbone.js?

•  The Traditional Web

•  MVC with Backbone.js

•  Templating with Underscore.js

•  Single-Page Apps

•  The Future

Page 3: Javascript Application Architecture with Backbone.JS

Intro

•  Graduated in 2011

•  B.S. and M.S. Computer Science

•  Co-Founder of Pixelapse

•  Full-Stack + Front-end + Design

Page 4: Javascript Application Architecture with Backbone.JS

Github for Designers Version Control + Backup + Collaboration

http://vimeo.com/pixelapse/pixelapse

Page 5: Javascript Application Architecture with Backbone.JS

Pixelapse Stack

•  Web App: Postgres 9.2 + Rails 3.2 (Ruby) + Backbone.js 1.0

•  File Server: Tornado 3.0.1 (Python)

•  Client Apps: Python + (Object-C or Qt)

•  Heroku + Amazon S3 + PubNub

Page 6: Javascript Application Architecture with Backbone.JS

What is Backbone.js?

Page 7: Javascript Application Architecture with Backbone.JS

Backbone.js is many things...

•  Javascript Model-View-Controller (MVC) framework

•  Templating engine (through Underscore.js)

•  Single-page apps (through router & history)

Page 8: Javascript Application Architecture with Backbone.JS

Why Backbone.js?

•  Very flexible

•  can support multiple ways of structuring things; do not have to use everything; tailor to your needs

•  Huge community

•  easy to find resources; get answers; multiple extensions

Page 9: Javascript Application Architecture with Backbone.JS

The Traditional Web

Page 10: Javascript Application Architecture with Backbone.JS

How web app works?

Client Server Database

Display  rendered  HTML  1.  Get  data  from  database  2.  Format  into  HTML  tags  3.  Send  back  to  client  

Holds  data  

Page 11: Javascript Application Architecture with Backbone.JS

The Traditional Way

Client Server Database

<ul>      <li>David</li>      <li>John</li>      <li>Jack</li>      <li>Dan</li>  </ul>  

ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...  

<ul>      <%  posts.each  do  |p|  %>          <li><%=  p.name  %></li>      <%  end  %>  </ul>  

• Great for UI only sites. Bad for dynamic interactive web apps.

• E.g. I want to update Dan to Peter

MVC

Page 12: Javascript Application Architecture with Backbone.JS

E.g. Updating Attributes

Server Database

<ul>      <li  id='n1'>David</li>      <li  id='n2'>John</li>      <li  id='n3'>Jack</li>      <li  id='n4'>Dan</li>  </ul>  

ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...  

<ul>      <%  posts.each  do  |p|  %>          <li><%=  p.name  %></li>      <%  end  %>  </ul>  

Client

1.  Encode UI with additional information like data-ids

2.  $.ajax(...) call to update ID: 4 with Peter

3.  $(“#n4”).html(“Peter”)���

Page 13: Javascript Application Architecture with Backbone.JS

E.g. Creating Items

Server Database

<ul>      <li  id='n1'>David</li>      <li  id='n2'>John</li>      <li  id='n3'>Jack</li>      <li  id='n4'>Dan</li>  </ul>  

ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...  

<ul>      <%  posts.each  do  |p|  %>          <li><%=  p.name  %></li>      <%  end  %>  </ul>  

Client

1.  $.ajax(...) call to create new item

2.  $(“ul”).append("<li id='" + data.id + "'>" + data.name + "</li>")���

Duplication of logic

Page 14: Javascript Application Architecture with Backbone.JS

Interactive Web Examples

Page 15: Javascript Application Architecture with Backbone.JS

Web Getting More Interactive

•  The motivation for robust Javascript Application Architecture

•  No callback hell

•  Easy to update UI, easy to update server

•  Examples

•  Gmail, Facebook, Twitter, Pixelapse, etc.

Page 16: Javascript Application Architecture with Backbone.JS

MVC with Backbone.js

Page 17: Javascript Application Architecture with Backbone.JS

Javascript UI

Server Database ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...  

<ul>      <%  posts.each  do  |p|  %>          <li><%=  p.name  %></li>      <%  end  %>  </ul>  

Client

1.  Move rendering logic to client-side

2.  Sometimes called Javascript UI because Javascript is doing the templating now (not the server)���

Page 18: Javascript Application Architecture with Backbone.JS

Collection

Collection View

Client-Side MVC

Model Model View

REST API

Client Server Database ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...  

<ul>  

<li>name</li>  

.json  var  list  =    

1.  Add/Modify/Delete item

2.  Updates server + updates UI���

MVC

ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...  

Page 19: Javascript Application Architecture with Backbone.JS

Collection

Client-Side MVC

Model

REST API

Client Server Database ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...  

Let’s us see how Backbone help us update the server when we modify the list���

Page 20: Javascript Application Architecture with Backbone.JS

Collection

Server REST API

Model

REST API

Client Server Database ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...  

Page 21: Javascript Application Architecture with Backbone.JS

Web Server API

•  CRUD - Create, Read, Update, Delete

•  Maps to HTTP methods: POST, GET, PUT, DELETE

•  Scaffolding on most modern web frameworks like Rails or Django

Page 22: Javascript Application Architecture with Backbone.JS

RESTful API

Action Method URL

Create POST /posts

Read GET /posts(/:id)

Update PUT /posts/:id

Delete DELETE /posts/:id

Page 23: Javascript Application Architecture with Backbone.JS

Create

var  PostList  =  Backbone.Collection.extend({      model:  PostItem,  //Reference  to  collection's  model      url:  '/posts'  });    post_list  =  new  PostList();    //I  want  to  create  a  new  item  in  the  collection  post_list.create({      title:  'New  Title'  });      //Backbone  will  automatically  request  '/posts'  with  POST  

method  attaching  the  data  

Page 24: Javascript Application Architecture with Backbone.JS

Read

//I  want  to  get  a  list  of  posts  post_list.fetch();    //Backbone  will  automatically  request  '/posts'  with  GET  

method          //I  want  to  get  one  post  item  =  post_list.get(1);  item.fetch();    //Backbone  will  automatically  request  '/posts/1'  with  GET  

method  

Page 25: Javascript Application Architecture with Backbone.JS

Update

var  PostItem  =  Backbone.Model.extend({      urlRoot:  '/posts'  });    //I  want  to  change  some  attributes  of  an  item  (id:  8)  item  =  post_list.get(8);  item.set('title',  'New  Title');  item.save();    //Backbone  will  automatically  request  '/posts/8'  with  PUT  

method  attaching  the  data  

Page 26: Javascript Application Architecture with Backbone.JS

Delete

//I  want  to  change  some  attributes  of  an  item  (id:  8)  item  =  post_list.get(8);  item.destroy();    //Backbone  will  automatically  request  '/posts/8'  with  DELETE  

method  

Page 27: Javascript Application Architecture with Backbone.JS

Quick Summary

Backbone Action Method URL

collection.create() Create POST /posts

collection.fetch() model.fetch() Read GET /posts(/:id)

model.set(...) model.save() Update PUT /posts/:id

model.destroy() Delete DELETE /posts/:id

Page 28: Javascript Application Architecture with Backbone.JS

Collection

Collection View

Client-Side MVC

Model Model View

REST API

Client Server Database ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...  

ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...   .json  

<ul>  

<li>name</li>  

var  list  =    

1.  Add/Modify/Delete item

2.  Updates server + updates UI���

✓"

✓"

?"

?"

Page 29: Javascript Application Architecture with Backbone.JS

Backbone Events

•  Attributes changes triggers a Backbone Sync event

•  Also triggers ‘change’ event, re-renders UI accordingly

Page 30: Javascript Application Architecture with Backbone.JS

Create

var  PostListView  =  Backbone.View.extend({      el:  "ul",      initialize:  function()  {          this.collection.bind('add',  this.addPostItem);          this.collection.bind('reset',  this.render,  this);    },      render:  function()  {          $(this.el).html("");          this.collection.each(this.addPostItem);          return  this;  },      addPostItem:  function(item)  {          var  post_item_view  =  new  PostItemView({model:  item});          $(this.el).append(post_item_view.render().el);  }  });      //Every  time  an  item  is  ADD-­‐ed  to  the  collection,  

addPostItem()  would  be  called  

Page 31: Javascript Application Architecture with Backbone.JS

Create

post_list.create({      title:  'New  Title'  });      1:  request  '/posts'  with  POST  method  attaching  the  data  //Automatically  tell  the  server  new  item  is  created    2:  addPostItem()  will  automatically  be  called  //Automatically  update  the  UI  to  include  new  item  

Page 32: Javascript Application Architecture with Backbone.JS

Read

var  PostListView  =  Backbone.View.extend({      el:  "ul",      initialize:  function()  {          this.collection.bind('add',  this.addPostItem);          this.collection.bind('reset',  this.render,  this);    },      render:  function()  {          $(this.el).html("");          this.collection.each(this.addPostItem);          return  this;  },      addPostItem:  function(item)  {          var  post_item_view  =  new  PostItemView({model:  item});          $(this.el).append(post_item_view.render().el);  }  });      //Every  time  a  collection  is  RESET-­‐ed,  render()  would  be  

called  

Page 33: Javascript Application Architecture with Backbone.JS

Read

post_list.fetch();  //Backbone  0.9  post_list.fetch({reset:true});  //Backbone  1.0    1:  request  '/posts'  with  GET  method  //Get  list  of  posts  from  server    2:  render()  will  automatically  be  called        loop  through  each  item  (from  the  list  of  posts)        for  each  item,  append  to  the  el  (<ul>)  //Automatically  update  the  UI  with  list  of  items  

Page 34: Javascript Application Architecture with Backbone.JS

Update

var  PostItemView  =  Backbone.View.extend({      tagName:    "li",      initialize:  function()  {          this.model.on('change',  this.render,  this);          this.model.on('destroy',  this.remove,  this);      },      render:  function()  {          $(this.el).html('<h1>'  +  this.model.get('name')  +  '</

h1>');          return  this;      },  });    //Every  time  an  item  has  CHANGE-­‐ed,  render()  would  be  called  

Page 35: Javascript Application Architecture with Backbone.JS

Update

item  =  post_list.get(8);  item.set('title',  'New  Title');  item.save();    1:  request  '/posts/8'  with  PUT  method  attaching  the  data  //Automatically  tell  server  that  item  has  changed    2:  render()  will  automatically  be  called  //Automatically  update  the  UI  to  include  the  changes  

Page 36: Javascript Application Architecture with Backbone.JS

Delete

var  PostItemView  =  Backbone.View.extend({      tagName:    "li",      initialize:  function()  {          this.model.on('change',  this.render,  this);          this.model.on('destroy',  this.remove,  this);      },      remove:  function()  {          $(this.el).fadeOut(300,  function()  {  $

(this).remove();  });      },  });    //Every  time  an  item  is  DESTROY-­‐ed,  remove()  would  be  called  

Page 37: Javascript Application Architecture with Backbone.JS

Delete

item  =  post_list.get(8);  item.destroy();    1:  request  '/posts/8'  with  DELETE  method  //Automatically  tell  server  that  item  has  been  deleted    2:  remove()  will  automatically  be  called  //Automatically  update  the  UI  to  remove  the  item  

Page 38: Javascript Application Architecture with Backbone.JS

Collection

Collection View

Client-Side MVC

Model Model View

REST API

Client Server Database ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...  

1.  Add/Modify/Delete item

2.  Updates server + updates UI���

✓"

✓"

✓"

✓"

ID   Name  

1   David  

2   John  

3   Jack  

4   Dan  

...   ...   .json  

<ul>  

<li>name</li>  

var  list  =    

Page 39: Javascript Application Architecture with Backbone.JS

Quick Summary

Backbone Server Sync UI Sync

collection.create() POST “/posts” Triggers “add” on collection

collection.fetch() model.fetch() GET “/posts(/:id)” Triggers “reset” on collection

model.set(...) model.save() PUT “/posts/:id” Triggers “change” on model

model.destroy() DELETE “/posts/:id” Triggers “destroy” on model

Page 40: Javascript Application Architecture with Backbone.JS

Tips & Tricks

•  {silent:true} to prevent event triggers

•  item.set("title", "Silent", {silent: true});

•  {wait: true} if you'd like to wait for the server respond before updating the UI

•  post_list.create({ title: "Waiting..." }, {wait: true})

Page 41: Javascript Application Architecture with Backbone.JS

Templating with Underscore.js

Page 42: Javascript Application Architecture with Backbone.JS

Update

var  PostItemView  =  Backbone.View.extend({      tagName:    "li",      initialize:  function()  {          this.model.on('change',  this.render,  this);          this.model.on('destroy',  this.remove,  this);      },      render:  function()  {          $(this.el).html('<h1>'  +  this.model.get('name')  +  '</

h1>');          return  this;      },  });  

• Ugly and clumsy to write inline html like this

Page 43: Javascript Application Architecture with Backbone.JS

_.template

•  Backbone’s hard dependency

•  Write templates like what you expect from Rails, Django, etc. but on the client-side

•  Interpreted and rendered by the browser

Page 44: Javascript Application Architecture with Backbone.JS

Basic Example

<script  type="text/template"  id="post_item_template">        <h1>{{=  post.get("title")  }}</h1>      <h6>{{=  post.get("name")  }}</h6>      <p>{{=  post.get("content")  }}</p>    </script>  

Page 45: Javascript Application Architecture with Backbone.JS

_ is basically Javascript

<script  type="text/template"  id="post_item_template">        <h1>{{=  post.get("title")  }}</h1>      <h6>{{=  post.get("name")  }}</h6>      <p>{{=  post.get("content")  }}</p>        {{  _.each(post.get("comments"),  function(c,  i)  {  }}          {{  if  (i<6)  {  }}                <p>{{=  c.body  }}</p>            {{  }  }}      {{  });  }}    </script>  

Page 46: Javascript Application Architecture with Backbone.JS

Backbone without _

render:  function()  {      $(this.el).html('<h1>'  +  this.model.get('title')  +  '</

h1>');  }  

Page 47: Javascript Application Architecture with Backbone.JS

Backbone with _

template:  _.template($('#post_item_template').html()),      render:  function()  {      $(this.el).html(this.template(  {  post:  this.model  }  ));  }        <script  type="text/template"  id="post_item_template">      <h1>{{=  post.get("title")  }}</h1>  </script>  

Page 48: Javascript Application Architecture with Backbone.JS

Update with _ template

var  PostItemView  =  Backbone.View.extend({      tagName:    "li",      template:  _.template($('#post_item_template').html()),      initialize:  function()  {          this.model.on('change',  this.render,  this);          this.model.on('destroy',  this.remove,  this);      },      render:  function()  {          $(this.el).html(this.template(  {  post:  this.model  }  ));          return  this;      },  });    //Every  time  an  item  has  CHANGE-­‐ed,  render()  would  be  called,  

and  the  template  will  be  used  

Page 49: Javascript Application Architecture with Backbone.JS

Tips and Tricks

Conflict  with  Rails  templating.  Changed  from    <%=  post.get(“title”)  %>  to  {{=  post.get(“title”)  }}          _.templateSettings  =  {      interpolate:  /\{\{\=(.+?)\}\}/g,      escape:  /\{\{\-­‐(.+?)\}\}/g,      evaluate:  /\{\{(.+?)\}\}/g  };  

Page 50: Javascript Application Architecture with Backbone.JS

Single Page Apps

Page 51: Javascript Application Architecture with Backbone.JS

What is Single Page App?

•  Single Page Apps a.k.a. Complete Javascript UI a.k.a. Single-Page Javascript UI

•  No refresh. Everything is AJAX-ed.

•  Feels more like an app, less like a website (less request/respond feel)

•  E.g. Twitter, Gmail, iCloud, Google Docs

Page 52: Javascript Application Architecture with Backbone.JS

Key Ideas

•  URL should change (so that bookmarks still work/links copy still work)

•  Back button should work

•  Loading UI

•  Javascript handles the routes (the URLs)

Page 53: Javascript Application Architecture with Backbone.JS

Backbone Router

var  AppRouter  =  Backbone.Router.extend({      routes:  {          "posts/:id":  "getPost",          "contact":  "getContact",          "*actions":  "defaultRoute"      },      getPost:  function(id)  {          //execute  stuff  here      },      ...  }    var  app_router  =  new  AppRouter;  app_router.navigate("posts/123",  true);  

Page 54: Javascript Application Architecture with Backbone.JS

HTML5 Push State

•  The old way: location.hash (e.g. #help)

•  Re-write location bar URL

•  Making sure Back Button still works

•  IE 10 onwards

•  http://caniuse.com/#search=history

Backbone.history.start({pushState:  true});  

Page 55: Javascript Application Architecture with Backbone.JS

DEMO

Page 56: Javascript Application Architecture with Backbone.JS

Quick Recap

•  Javascript MVC framework

•  Backbone Sync automatically syncs with your backend

•  And automatically updates your UI

•  Templating engine (through Underscore.js)

•  Single-page apps (through router & history)

Page 57: Javascript Application Architecture with Backbone.JS

The Future...

Page 58: Javascript Application Architecture with Backbone.JS

So... Single-Page Apps are the way to go?

•  Very hard to maintain. Gets complex really fast.

•  Client code can become “heavy” (easily see 2-3x increase in JS file size)

•  SEO will be challenging

•  Have to think about User Experience

•  Not for older browsers

Page 59: Javascript Application Architecture with Backbone.JS

Should you make single-page apps?

•  Who are your users? (modern browsers?)

•  Are there a lot of interactions? Does the whole site needs to be a single app?

•  Does your web app need to be in real-time?

Page 60: Javascript Application Architecture with Backbone.JS

Many other frameworks...

•  AngularJS (by Google; use traditional JS)

•  Ember.js (very structured; convention over configuration)

•  KnockoutJS (two way bindings)

•  Resources:

•  http://coding.smashingmagazine.com/2012/07/27/journey-through-the-javascript-mvc-jungle/

Page 61: Javascript Application Architecture with Backbone.JS

Stack

•  Use well establish frameworks

•  Large community, lots of resources

•  Good conventions (like RESTful, json, etc)

•  Easy to find plug-ins, extensions (less re-write)

•  Recommendations

•  Web frameworks: Rails, Django, (Node.js)

•  Javascript MVC: Backbone (Angular, Ember, Knockout)

Page 62: Javascript Application Architecture with Backbone.JS

Feel free to reach out

•  https://github.com/lominming/rails-backbone-example

•  [email protected]

•  @lominming

•  Any Javascript, Backbone stuff

•  General startup stuff