2. Outline
About Me
Why Backbone?
Pain Points with Backbone
Design Patterns/Best Practices
Marionette.js
3. About Me (@yagudaev)
Co-founder of 0idle.com – an online marketplace for
event organizers to find the perfect venue.
Built 0idle using Rails + Backbone.js
Entrepreneur and Rails Developer
Worked with Node.js
Started Winnipeg.js User Group
Consulting/Freelance work
4. Why Backbone.js?
Simple
Flexible – use only the parts you need
Easy to integrate into existing code
Provides structure to your app
Proven
Well Documented (for the most part )
Good for hybrid apps
5. 5
A Pain in the Back...
Due to its un-opinionated approach, backbone can be a
real pain in the a**.
No clear guidelines
Lots of boilerplate code
Does not provide helpers to solve common problems
Easy to get memory leaks by not being careful when
using events (zombie views)
6. Underline Principle for this talk
In any web system, the server should have the final say
Therefore, lets start developing server-side code first
Server-side code is easier to test (simple request/response)
Client-side functionality is to be considered as an added
bonus in agile software development
You can do without backbone when you first start a project
(KISS)
Assumption: a team of one
8. Scoping Your Selectors
Problem: Overly generic jQuery selectors can cause
unexpected behavior when adding a new feature to a
particular area of an application.
Example:
$(‘.btn-add’).click(addNewReply);
// Will conflict with:
$(‘.btn-add’).click(addNewMessage);
Solution: Use a backbone View
10. File Structure
Problem: Your one javascript file becomes long and hard to
maintain. You need a better way to separate concerns.
Solution: Break down project into folders based on object
types in backbone with a main.js file that acts as the entry
point of the application and defines a namespace.
Notes: you will need to use a make or a make like solution to
stitch the files together (e.g. Rails asset pipeline or h5bp build
tool).
Note 2: Keep it simple. Avoid using an AMD loader like
RequireJS at this stage.
11. |____application.js -- manifest file (can have more than one)
|____collections/
|____lib/
|____main.js
|____models/
|____templates/
|____views/
| |____messages_view.js
| |____replies_view.js
|____vendor/
| |____backbone.js
| |____jquery.js
| |____underscore.js
File Structure (folders)
15. Templates
Problem: You need to dynamically generate html
content, but do not want pollute your js code with html
markup.
Example: a dynamic file uploader allowing the user to
upload any number of files.
Solution: place your html inside a script tag and use
jQuery to extract the content of the template and then
render it to the page. Alternatively you can use JST to
give each template a separate file.
18. Template Sharing
Problem: You have a template you want rendered both
on the client and server.
Example: you have a photo uploader that lets the user
upload multiple photos and see photos that were
already uploaded.
Solution: refactor the template into a mustache
template and provide access to it from both the client
and the server.
Limitation: cannot use helper methods (unless you are
using Node.js)
21. Client-side View Injection
Problem: Similar to Template Sharing, but you are
interested in re-using server-side helpers and do not care
about filling in information in the template.
Example: a survey application which displays existing
questions and allows to dynamically add new questions.
Solution: pre-render a partial somewhere in the DOM
and to make it accessible to the client side code.
22. 22
Client-side View Injection
// ...
addSpace: function() {
var html = this.$('.btnAdd').data('view');
$('body').append(html);
}
// ...
<a href="#" class="btnAdd" data-view="<%= render 'space_card' %>">
Add Space
</a>
23. View Helpers
Problem: You want to change the format in which your
information is displayed in the view, but the logic will
be too complicated to be added directly in the view.
Example: Format a date.
Solution: Define a view helper to handle this
functionality.
25. Bootstrap Data
Problem: You need to share data between the client-
side code and the server code. At the same time you
would like to avoid incurring the cost of another HTTP
request.
Example: You want to check if a user is logged in
before you allow them to IM other users.
Solution: Use server-side processing to initialize your
model(s).
26. 26
<script>
(function() {
var user;
// preprocessed file to bootstrap variables from ruby to javascript
window.ZI = {
Config: {},
Models: {},
Collections: {},
Views: {},
Lib: {},
currentUser: function() {
var user_data = <%=raw current_user ? current_user.to_json : 'null'
%>;
if (user_data) return user = user || new ZI.Models.User(user_data);
return null;
}
};
// ... after the model has been loaded ...
console.log(ZI.currentUser() === null); // not logged in
console.log(ZI.currentUser() !== null); // logged in
})();
</script>
27. 27
Bootstrap Data (e.g. 2)
var photos = new Backbone.Collection;
photos.reset(<%= @photos.to_json %>);
28. Mixin
Problem: You have code that is common between
several views or models, but it does not make sense to
move code into a parent class.
Example: Code that allows you to open a message
dialog and can be opened from several different views.
Solution: Use a mixin to include the common code in
the target views or models.
31. Parent-Child (Sub Views)
Views
Problem: You have a view that needs to communicate
with another view and can be thought of as logically
containing that view.
Example: Updating a dropdown after a user creates a
new item through a modal dialog.
Solution: Create a reference to the child view from the
parent view and listen on events fired by the child view.
35. Two-Way Bindings
Problem: You need to dynamically and automatically
update a UI element when the underling data changes.
Example: Recalculate and display the total amount in a
shopping cart if the quantity of any of the items
changes.
Solution: Use a two-way binding plugin for backbone
called backbone.stickit.
* This is how backbone is good for multipage application * Great if you concatenate your javascript into one file and run on all your pages * Helps prevent unexpected behavior when adding functionality to the same area of your application
* based on rails file structure * vendor contains 3rd party libraries * views, models, collections and templates contain their respective backbone object types * lib - libraries you write to help you throughout your application * application.js - simple manifest file, describes build order
- main.js is the entry point of our application - defines a namespace we will use in all our other files to call our code
* make sure to use a script tag and not just any dom element * otherwise, may generate invalid markup which will result in bugs * we grab content from template in script tags using the ID and add it to the dom
remind them about what our application does
* initialize a collection
Remember to talk about the potential for memory leaks (and unwanted behavior) Go over slide with craig
* Have not used before, but look at it * Flexible and can use only the pieces you need * If nothing else it provides us with formal language to talk about concepts * View Management is biggest take away * Layout -> contains regions -> views * Regions manage screen real-estate, views just know how to render themselves but nothing about where they are rendered. * Prevent zombie views * Adds the concepts of controllers