This document provides an overview and summary of Javascript application architecture using Backbone.js and Underscore.js. It discusses the traditional web architecture with server-side rendering compared to client-side MVC frameworks. It then covers the basics of Backbone.js including models, collections, RESTful APIs, and how Backbone handles CRUD operations and tying the front-end to backend data. Templating with Underscore.js and building single page apps are also mentioned.
8. 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
10. 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
11. 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
12. 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”)
13. 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
15. 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.
17. 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)
21. 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
22. RESTful API
Action
Method
URL
Create
POST
/posts
Read
GET
/posts(/:id)
Update
PUT
/posts/:id
Delete
DELETE
/posts/:id
23. 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
24. 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
25. 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
26. 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
27. 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
29. Backbone Events
• Attributes changes triggers a Backbone Sync
event
• Also triggers change event, re-renders UI
accordingly
30. 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
31. 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
32. 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
33. 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
34. 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
35. 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
36. 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
37. 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
39. 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
40. 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})
42. 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
43. _.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
48. 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
49. Tips and Tricks
Conflict
with
Rails
templating.
Changed
from
%=
post.get( title )
%
to
{{=
post.get( title )
}}
_.templateSettings
=
{
interpolate:
/{{=(.+?)}}/g,
escape:
/{{-‐(.+?)}}/g,
evaluate:
/{{(.+?)}}/g
};
51. 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
52. 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)
53. 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);
54. 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});
58. 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
59. 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?
60. 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/
61. 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)
62. Feel free to reach out
• https://github.com/lominming/rails-backbone-
example
• minming@minming.net
• @lominming
• Any Javascript, Backbone stuff
• General startup stuff
Hinweis der Redaktion
Why there’s a need for Backbone for Pixelapse
Demo CRUD on traditional.
Demo AJAX form on the traditional page.
Pixelapse.com - Folder actions. New folder, drag-and-drop, comments section. Gmail.com - starring, etc.
Pixelapse.com - Folder actions. New folder, drag-and-drop, comments section. Gmail.com - starring, etc.
Demo backbone page
Demo json at URL Show the method called at form (after submit)
Demo backbone page
Demo backbone page
Demo backbone page
Demo backbone page
Demo ID trick
Bad example: google search for a location Loading UI: Twitter spinner, facebook, pixelapse animation
SEO: No links to crawl and follow. Information is JSON-ed.
Real-time like Twitter search, news, chat, feed... No need real-time blogs? articles...