BOOSTING THE
CLIENT-SIDE WITH
Jan 8th, 2014
AGENDA
- Javascript & Hyperspace
- Web architecture
- Client-side vs. Server-side
- REST
- JSON
- MVC
- Web frameworks vs. Client-side apps
______________________________________________
Boosting the client-side with Backbone.js
AGENDA
- Backbone.js
- Model
- Collection
- View
- Router
- Dynamic templates
______________________________________________
Boosting the client-side with Backbone.js
Javascript & Hyperspace
-
Hyperspace: the next dimension above.
- We can only see up to the current dimension.
- Consider 3 dimensions for a browser:
-
Rendering: HTML/CSS.
-
Elements: DOM.
-
Behavior: JS.
- The 4th dimension is its hyperspace.
How would it be?
______________________________________________
Boosting the client-side with Backbone.js
Web architecture
- Application ends:
-
Front-end: interacts with a human.
-
Back-end: handles business logic and data/services access.
- Application sides:
-
Client-side: runs on user browser/device.
-
Server-side: runs on a server.
THEY ARE NOT THE SAME THING!
______________________________________________
Boosting the client-side with Backbone.js
client-side vs. server-side
- Isolated web-apps (client-side only):
-
Only front-end. Ex: "BMI calculator".
-
Front-end and back-end. Ex: "TODO list manager" persisting on HTML5 local storage on the browser.
______________________________________________
Boosting the client-side with Backbone.js
client-side vs. server-side
- Integrated web apps (client-side and server-side):
-
Front-end on client-side + back-end on server-side. Response is hypertext over HTTP. Ex: "TODO list manager" in a web framework (Struts, JSF, Rails).
-
Front-end and back-end on client-side + REST back-end on server-side. Response is data over HTTP. Ex: "Trello" implemented in Backbone.js.
______________________________________________
Boosting the client-side with Backbone.js
REST
- REpresentational State Transfer.
- Stateless architectural style for distributed systems, based on HTTP protocol:
- HTTP methods are verbs (actions).
- URIs are nouns (resources).
- HTTP status codes are meaningful actions responses, like 200 (ok), 404 (not found), 500 (internal server error).
______________________________________________
Boosting the client-side with Backbone.js
REST
- REST actions addressed today:
-
HTTP GET:
retrieves a resource. Ex:
GET
/users/1
retrieves the user which id = 1.
-
HTTP POST:
creates a resource. Ex:
POST
/users
creates an user (data on request body).
-
HTTP PUT:
updates a resource. Ex:
PUT
/users/1
updates the user which id = 1 (data on req. body).
-
HTTP DELETE:
removes a resource. Ex:
DELETE
/users/1
removes the user which id = 1.
______________________________________________
Boosting the client-side with Backbone.js
JSON
- JavaScript Object Notation.
- Universal format of data transference in JavaScript.
- Reduced size, simplified format, easy to parse -> good alternative to XML.
{
"name": "R2-D2",
"owners": ["Anakin", "Leia", "Luke"],
"attributes": {
"height": 0.96,
"mass": 32
}
}
______________________________________________
Boosting the client-side with Backbone.js
MVC
- Model-View-Controller.
- Architectural design pattern that leverages better application organization through separation of concerns:
-
Model: business data.
-
View: user interface.
-
Controller: connection and data input logic.
______________________________________________
Boosting the client-side with Backbone.js
MVC in Javascript
- Avoid "spaghetti code" (hard to read and maintain for the lack of structure).
- Overall maintainability is strongly improved. It makes it clear to identify where to change the code.
- Enables more objective unit tests.
- Modularity allows better distribution of tasks among the team.
MVC IS OUR HYPERSPACE!!
______________________________________________
Boosting the client-side with Backbone.js
WEB FRAMEWORKS vs. client-side apps
- Server-side web frameworks:
- Actions life cycle is managed and routed on the server-side.
- Server-side templates generating HTML from data.
- HTTP response transmitting hypertext (HTML).
- Every action demands a page reload.
- Actions are synchronous.
______________________________________________
Boosting the client-side with Backbone.js
WEB FRAMEWORKS vs. client-side apps
- Client-side apps:
- Actions life cycle is managed and routed on the client-side.
- HTTP response transmitting data (JSON, XML, etc...).
- Client-side templates generating HTML from data.
- Actions DON'T demand any page reload.
- Actions can be asynchronous.
______________________________________________
Boosting the client-side with Backbone.js
backbone.js
- Javascript library that provides structure to client-side applications based on REST APIs using JSON.
- Created in 2010, it is currently used in big websites such as Airbnb, BitTorrent, Digg, Foursquare, Hulu, LinkedIn mobile, Pinterest, Trello, Walmart and Wordpress.
- Depends on Underscore.js and jQuery (or similar libs such as Zepto.js, with varying degrees of compatibility).
______________________________________________
Boosting the client-side with Backbone.js
backbone.js
-
SPA (Single-Page Application): architectural style about doing a single page load for the whole application.
-
Elements: Model, Collection, View and Router.
Backbone.js isn't a classic MVC framework...
...but it belongs to MV* family, which similar goals!!
______________________________________________
Boosting the client-side with Backbone.js
Model
- Stores and manipulates data.
- Communicates with REST APIs.
- Supports parsing, translation, validation and business logic processing.
var CardModel = Backbone.Model.extend({
urlRoot : '/api/cards'
});
-
urlRoot
specifies the base URL for REST calls, which will precede the REST actions.
______________________________________________
Boosting the client-side with Backbone.js
Model
- REST methods:
-
fetch(options)
: Retrieves an entity via HTTP GET.
-
save(attributes, options)
: Creates an entity via HTTP POST (if the object doesn't have an id yet) or updates an entity via HTTP PUT (if the object has an id already).
-
destroy(options)
: Removes an entity via HTTP DELETE.
______________________________________________
Boosting the client-side with Backbone.js
Model
- Parâmetros:
-
attributes
: Object containing data to be saved.
-
options
: Object containing configuration such as:
-
url
: Connection URL with the server-side, overwriting urlRoot
.
-
success
: Callback function for success response.
-
error
: Callback function for error response or timeout .
______________________________________________
Boosting the client-side with Backbone.js
Model
var model = new CardModel({
id: 1
});
// GET /api/cards/1
model.fetch({
success: function(model, response, options) {
console.log('Success! Model = ' + model.toJSON());
},
error: function(model, response, options) {
console.log('Error or timeout.');
}
});
______________________________________________
Boosting the client-side with Backbone.js
Model
- Some common methods:
-
get(attribute)
: Gets the value of an attribute from the Model. Ex: card.get('title');
-
set(attribute, value)
: Sets a value for an attribute on the Model. Ex: card.set('title', 'Project X');
-
toJSON()
: Returns a copy of the Model data in JSON. Ex: card.toJSON();
______________________________________________
Boosting the client-side with Backbone.js
Collection
- Ordered list of Models.
- Creates models from a JSON array.
- Implements array methods from Underscore.js library.
var CardCollection = Backbone.Collection.extend({
model : CardModel,
url : '/api/cards'
});
-
model
specifies the Model to be created.
-
url
specifies the base URL for REST calls, which will precede the REST actions.
______________________________________________
Boosting the client-side with Backbone.js
Collection
- Collections complement the REST API from Models with this method:
-
fetch(options)
: Retrieves an array of entities via HTTP GET, populates each entity as a Model and inserts it in the Collection.
______________________________________________
Boosting the client-side with Backbone.js
Collection
var cardCollection = new CardCollection();
// GET /api/cards
cardCollection.fetch({
success: function(collection, response, options) {
console.log('Success! Collection = ' +
collection.toJSON());
},
error: function(collection, response, options) {
console.log('Error or timeout.');
}
});
______________________________________________
Boosting the client-side with Backbone.js
Collection
- Some common methods:
-
get(id)
: Retrieves a Model a from its id. Ex: collection.get(12);
-
at(index)
: Retrieves a Model from its position on the Collection. Ex: collection.at(1);
-
add(model)
: Adds a Model to the Collection. Ex: collection.add({'title', 'Project X'});
-
remove(id)
: Removes a Model from the Collection. Ex: collection.remove(12);
______________________________________________
Boosting the client-side with Backbone.js
Collection
- Some common methods:
-
toJSON()
: Returns a copy of the Collection data in JSON. Ex: collection.toJSON();
-
where(attributes)
: Returns just the Collection elements which match the given criteria. Ex: collection.where({'type': 'PROJECT'});
-
pluck(attribute)
: Returns an array with extracted values from Collection elements, based on the given attribute. Ex: collection.pluck('title');
______________________________________________
Boosting the client-side with Backbone.js
View
- Manages the presentation logic and events.
- Renders an HTML template which can be added to the DOM, consuming data from Models or Collections.
- The HTML template can be dynamically generated.
______________________________________________
Boosting the client-side with Backbone.js
View
- Main attributes to be implemented:
-
events
: Events mapping object, like this:
'CSS selector':
function / 'function'
-
render()
: Method that should contain all the View logic, in three steps:
- Retrieving/preparing the HTML template.
- Rendering the HTML template from a Model or Collection.
- Inserting the rendering result into
el
attribute.
______________________________________________
Boosting the client-side with Backbone.js
View
- Some common View attributes:
-
el
: HTML element rendered by this View. It can be accessed via $el
as a jQuery/Zepto.js object.
-
id
: The id
attribute from el
.
-
className
: The class
attribute from el
-
tagName
: The HTML tag to be used by el
.
-
remove()
: Removes the View from the DOM and remove all event listeners binded to it.
______________________________________________
Boosting the client-side with Backbone.js
View
var CardView = Backbone.View.extend({
events: {
'click button.close': function(e) {
e.preventDefault();
this.remove();
}
},
render: function() {
var result =
'<h1>' + this.model.get('title') + '</h1>' +
'<button class="close">Close</button>');
this.$el.html(result);
}
});
______________________________________________
Boosting the client-side with Backbone.js
View
- View parameters:
-
el
: An existing HTML element can be provided to receive the content rendered by the View.
-
model
: The Model to be consumed by render()
.
-
collection
: The Collection to be consumed by render()
.
______________________________________________
Boosting the client-side with Backbone.js
View
var cardModel = new CardModel({ id: 1 });
cardModel.fetch({
success: function(model, response, options) {
var cardView = new CardView({
model: cardModel
);
cardView.render();
$('#contents').append(cardView.el);
},
error: function(model, response, options) {
console.log('Error or timeout.');
}
});
______________________________________________
Boosting the client-side with Backbone.js
Router
- Allows for URL handling and routing.
- Controls the navigation history.
- Avoids direct requests to the server-side.
- Main attribute:
-
routes
: Mapping routes object, like this:
'uri': function / 'function'
______________________________________________
Boosting the client-side with Backbone.js
Router
var AppRouter = Backbone.Router.extend({
routes : {
'' : 'viewAll',
'card/:id' : 'viewCard',
'*path' : 'viewAll'
},
viewAll: function() { ... },
viewCard: function(id) { ... }
});
______________________________________________
Boosting the client-side with Backbone.js
Router
- It is necessary to call
Backbone.history.start()
to start the routes monitoring by the Routers.
- Pass
{pushState: true}
to it in order to use HTML5 pushState. Otherwise, the routing would use # after the URL query string..
var appRouter = new AppRouter();
Backbone.history.start({
pushState : true
});
______________________________________________
Boosting the client-side with Backbone.js
Dynamic templates
- On the View, the HTML template can be generated by any Javascript templating library such as Underscore.js, Mustache, Handlebars.js, dust.js, etc...
- It is the same idea of PHP, JSP, ERB, ASP - but now on the client-side.
- It is much more maintainable then concatenated strings.
______________________________________________
Boosting the client-side with Backbone.js
Dynamic templates
-
Handlebars.js: performative, flexible and easy to learn and to handle alternative.
{{#if children}}
<ul>
{{#each children}}
<li>{{title}}: {{description}}</li>
{{/each}}
</ul>
{{else}}
<p>There is no items!</p>
{{/if}}
- Will be covered on a next AC talk by Alysson Ferreira!
______________________________________________
Boosting the client-side with Backbone.js
Conclusion
- Client-side apps aim to reproduce the desktop experience on the web.
- Client-side apps can drastically reduce the time waited by the user for a feedback.
- Hence, the chances for the user to stay on the system are greatly increased.
- Backbone.js is a mature MV* alternative to structure client-side apps.
______________________________________________
Boosting the client-side with Backbone.js
Learn more
______________________________________________
Boosting the client-side with Backbone.js
CHALLENGE
Write a multiple-choice quizz about a subject of your preference as a client-side app using Backbone.js.
-
The user name and email should be collected.
-
5 possible answers per question.
-
Either just 1 or up to 3 answers per time.
-
At least 5 questions on the quizz.
-
Lastly the user must see a graph of all questions and answers from all users with % for each answer.
-
Any approach for persistence, as long it uses Models (REST backend, local storage, session object, cookie...).
- Send me the solution in a GitHub repo.
_____________________________________________
Boosting the client-side with Backbone.js