Upload
brian-mann
View
1.048
Download
2
Embed Size (px)
DESCRIPTION
I gave this talk July 31 at BackboneConf 2013 in Boston, MA backboneconf.com Backbone has been used to build some of the greatest web apps in the world. Chances are, you have one running in your tabs. But the gap from first starting Backbone to building a large application is enormous. In this talk, Brian Mann will focus on closing that gap, and pave the way for creating powerful and highly scalable Backbone Apps. One of the biggest pain points of Backbone is dealing with its boilerplate code. Let’s face it; Backbone is notorious for being small and un-opinionated. While an attractive feature, it unfortunately means automation and workflow falls on developer’s shoulders. This often results in bloated code bases, reinvented patterns, frustration, and wasted time. Instead of building your application’s infrastructure from scratch, Brian will show you how to become a much happier Backbone developer by demonstrating how to build modular Backbone apps using Marionette JS. For videos and screencasts visit: http://www.backbonerails.com
Citation preview
Little Opinions Big Possibilities
@BackboneRailsBrian Mann
The Tools and Patterns for Building Large Scale Backbone Applications
Atlanta, GA
What is a large scale application?
In my view, large-scale Javascript apps are non-trivial applications requiring significant developer effort to maintain, where most heavy lifting of data manipulation and display falls to the browser.
Addy Osmani “Patterns For Large-Scale JavaScript Application Architecture”
“
“
If working on a significantly large Javascript application, remember to dedicate sufficient time to planning the underlying architecture that makes the most sense. It's often more complex than you may initially imagine.
Addy Osmani “Patterns For Large-Scale JavaScript Application Architecture”
“
“
What is not a large scale application?
Raising
the Bar
Google Analytics
WordPress
Rdio
Pandora
• Multiple Routers
• View Management
• Nesting
• Cleanup
• Complex Events
• Lots of state changes
• Many Entities (Models / Collections)
Characteristics
= Ton of JS Files
Overcoming the gap
Engineering is serious business
Stop blaming Backbone.
<EMBRACE IT>
The essential premise at the heart of Backbone has always been to try and discover the minimal set of data-structuring (Models and Collections) and user interface (Views and URLs) primitives that are useful when building web applications with JavaScript.
...In an ecosystem where overarching, decides-everything-for-you frameworks are commonplace, and many libraries require your site to be restructured to suit their look, feel, and default behavior — Backbone should continue to be a tool that gives you the freedom to design the full experience of your web application.
Jeremy Ashkenas Releasing Backbone v1.0
“
“
MonolithicFrameworks
Focused Small Tools
Leverage the Eco-system
Pick the Right Tool
• 2-way Data-Binding
• Nested Collections
• Advanced Querying
• Filtering / Sorting
• Grids
• View Models and Computed Properties
Stickit / RivetsBB.AssociationsBB.QueryBB.ProjectionsBackGridBB.Mutators /BB.Computed
Fields
Application Architecture
What we get
• Routers
• Views
• Events
class Router extends Backbone.Router routes: "users" : "listUsers" "users/new" : "newUser" "users/:id" : "showUser" "users/:id/edit" : "editUser" "dashboard" : "showDashboard" "admin/users" : "listAdminUsers" "admin/users/:id" : "showAdminUser" "contacts" : "listContacts" "contacts/new" : "newContact" "contacts/:id" : "showContact" listUsers: -> users = new Users users.fetch() usersView = new View({collection: users}) $("#users").html(usersView.render().el)
What we get
• Routers
• Views
• Events
class Router extends Backbone.Router routes: "users" : "listUsers" "users/new" : "newUser" "users/:id" : "showUser" "users/:id/edit" : "editUser" "dashboard" : "showDashboard" "admin/users" : "listAdminUsers" "admin/users/:id" : "showAdminUser" "contacts" : "listContacts" "contacts/new" : "newContact" "contacts/:id" : "showContact" listUsers: -> users = new Users users.fetch() usersView = new View({collection: users}) $("#users").html(usersView.render().el)
What we get
• Routers
• Views
• Events
class Router extends Backbone.Router routes: "users" : "listUsers" "users/new" : "newUser" "users/:id" : "showUser" "users/:id/edit" : "editUser" "dashboard" : "showDashboard" "admin/users" : "listAdminUsers" "admin/users/:id" : "showAdminUser" "contacts" : "listContacts" "contacts/new" : "newContact" "contacts/:id" : "showContact" listUsers: -> users = new Users users.fetch() usersView = new View({collection: users}) $("#users").html(usersView.render().el)
What we get
• Routers
• Views
• Events
class Router extends Backbone.Router routes: "users" : "listUsers" "users/new" : "newUser" "users/:id" : "showUser" "users/:id/edit" : "editUser" "dashboard" : "showDashboard" "admin/users" : "listAdminUsers" "admin/users/:id" : "showAdminUser" "contacts" : "listContacts" "contacts/new" : "newContact" "contacts/:id" : "showContact" listUsers: -> users = new Users users.fetch() usersView = new View({collection: users}) $("#users").html(usersView.render().el)
What we get
• Routers
• Views
• Events
class Router extends Backbone.Router routes: "users" : "listUsers" "users/new" : "newUser" "users/:id" : "showUser" "users/:id/edit" : "editUser" "dashboard" : "showDashboard" "admin/users" : "listAdminUsers" "admin/users/:id" : "showAdminUser" "contacts" : "listContacts" "contacts/new" : "newContact" "contacts/:id" : "showContact" listUsers: -> users = new Users users.fetch() usersView = new View({collection: users}) $("#users").html(usersView.render().el)
What we get
• Routers
• Views
• Events
class Router extends Backbone.Router routes: "users" : "listUsers" "users/new" : "newUser" "users/:id" : "showUser" "users/:id/edit" : "editUser" "dashboard" : "showDashboard" "admin/users" : "listAdminUsers" "admin/users/:id" : "showAdminUser" "contacts" : "listContacts" "contacts/new" : "newContact" "contacts/:id" : "showContact" listUsers: -> users = new Users users.fetch() usersView = new View({collection: users}) $("#users").html(usersView.render().el)
• Application• App Modules
• -Router
• -Controllers
• -Specialized Views
• Components
• Mixins
• Entities
• Config
Specialized Objects
• Application• App Modules
• -Router
• -Controllers
• -Specialized Views
• Components
• Mixins
• Entities
• Config
Specialized Objects
• Application• App Modules
• -Router
• -Controllers
• -Specialized Views
• Components
• Mixins
• Entities
• Config
• Modules
• Messaging Bus
• Request
• Command
• Pub / Sub
Specialized Objects
Visualize Our App
ULTIMATE CONTAINER
APPLICATION
Application
EntitiesUsers Sales
Items
Contacts Notes
Components
Mixins
Config
Visualize Our App
ULTIMATE CONTAINER
APPLICATION
Application
EntitiesUsers Sales
Items
Contacts Notes
Components
Mixins
Config
Visualize Our App
ULTIMATE CONTAINER
APPLICATION
Application
EntitiesUsers Sales
Items
Contacts Notes
Components
Mixins
Config
Visualize Our App
ULTIMATE CONTAINER
APPLICATION
Application
EntitiesUsers Sales
Items
Contacts Notes
Components
Mixins
Config
APPLICATION INSTANCE
#header-region
#main-region
#footer-region
Application Regions
Storing Entitiesand Resources
New ControllerShow Controller
List Controller
Visualize Our App
RESOURCE AUTHORITY
APP MODULE
ApplicationApp Module
Handlers<Requests>
<Commands><Pub / Sub >
Router
New ControllerShow Controller
List Controller
Visualize Our App
RESOURCE AUTHORITY
APP MODULE
ApplicationApp Module
Handlers<Requests>
<Commands><Pub / Sub >
Router
THE GATEKEEPER
USERS
LIST
SHOW
NEW
ADMINUSERS
LIST
EDIT
DASHBOARDUSERS LIST
<App Request><App Command>
/users/users/:id/users/new
Visualize Our App
Visual Composer
ControllerItem View
Layout
Collection View
Application
Controller
App Module
Visualize Our App
Visual Composer
ControllerItem View
Layout
Collection View
Application
Controller
App ModuleController Concerns
It Giveth Life
layout = new List.Layout
Layout
Visualize Our App
Visual Composer
ControllerItem View
Layout
Collection View
Application
Controller
App Module
UnderstandsView Dependencies
usersCollection = App.request "user:entities"
Layout
Controller Concerns
USERS COLLECTION
Visualize Our App
Visual Composer
ControllerItem View
Layout
Collection View
Application
Controller
App Module
USERS COLLECTION
Listens & Respondsto View Events
Controller Concerns
Layout
Visualize Our App
Visual Composer
ControllerItem View
Layout
Collection View
Application
Controller
App Module
USERS COLLECTION
Listens & Respondsto View Events
Controller Concerns
Layout
@listenTo layout, "show", => @listUsers(usersCollection)
listUsers: (users) -> new List.CollectionView({ collection: users })
Visualize Our App
Visual Composer
ControllerItem View
Layout
Collection View
Application
Controller
App Module
Collection View
Controller Concerns
Layout
USERS COLLECTION+
layout.usersRegion.show(collectionView)
Layout
Visualize Our App
Visual Composer
ControllerItem View
Layout
Collection View
Application
Controller
App Module
Requests AdditionalServices / Components
Controller Concerns
Visualize Our App
Visual Composer
ControllerItem View
Layout
Collection View
Application
Controller
App Module
Spinner
COMPONENTS
Form
OK
Name:Address:
Grid
Controller Concerns
Item View
Visualize Our App
Visual Composer
ControllerItem View
Layout
Collection View
Application
Controller
App Module
Spinner
COMPONENTS
Form
OK
Name:Address:
Grid
Controller Concerns
Item View
Visualize Our App
Visual Composer
ControllerItem View
Layout
Collection View
Application
Controller
App Module
Spinner
COMPONENTS
Grid
Controller Concerns
Item View
Visualize Our App
Presentation Manager
View
Application
Controller
App Module
View
<DOM />Template
Visualize Our App
Presentation Manager
View
Application
Controller
App Module
View
<DOM />Template
Event Method When This Event Triggers
before:render onBeforeRender before view’s $el has been rendered into the DOM
render onRender view’s $el has been inserted, allowing you to work with the DOM
show onShow a!er a view has been inserted by a region into the DOM
dom:refresh onDomRefresh a!er a view has been shown but has been re-rendered at a later time
before:close onBeforeClose view has been told to close. return false to prevent it from closing
close onClose a!er view is closed. run custom code such as additional cleanup
Visualize Our App
Presentation Manager
View
Application
Controller
App Module
View
<DOM />Template
class App.Views.SomeView extends Base.View mixin: ["focusable", "selectable"] onRender: -> ## We know we’re rendered, so manipulate the DOM. ## Now’s a great time to initialize a jQuery plugin. onClose: -> ## We know we’re about to be closed down. ## This is when we unbind / cleanup things we may have initialized at an earlier point.
Visualize Our App
Presentation Manager
View
Application
Controller
App Module
View
<DOM />Template
class App.Views.SomeView extends Base.View mixin: ["focusable", "selectable"] onRender: -> ## We know we’re rendered, so manipulate the DOM. ## Now’s a great time to initialize a jQuery plugin. onClose: -> ## We know we’re about to be closed down. ## This is when we unbind / cleanup things we may have initialized at an earlier point.
initialize: -> someModel = new App.Models.someModel
Visualize Our App
Presentation Manager
View
Application
Controller
App Module
View
<DOM />Template
class App.Views.SomeView extends Base.View mixin: ["focusable", "selectable"] onRender: -> ## We know we’re rendered, so manipulate the DOM. ## Now’s a great time to initialize a jQuery plugin. onClose: -> ## We know we’re about to be closed down. ## This is when we unbind / cleanup things we may have initialized at an earlier point.
initialize: -> someModel = new App.Models.someModel
Visualize Our App
Presentation Manager
View
Application
Controller
App Module
View
<DOM />Template
Specialized Views
Item View
Model
Collection View
Collection
Layout
Visualize Our App
Presentation Manager
<DOM />Template
View
Application
Controller
App Module
View
Visualize Our App
Presentation Manager
<DOM />Template
View
Application
Controller
App Module
View
Visualize Our App
Presentation Manager
<DOM />Template
View
Application
Controller
App Module
View<section> <div id="git-comment"><%= @comment %></div> <div id="git-author"> Authored by <%= @author %> on <%= @date %> </div> <div id="git-diff"> Showing <%= @num_changed %> changed files with <%= @num_additions %> additions. </div></section>
Marionette JS
• Application
• App Router
• Controllers
• Specialized Views• Layouts & Regions
• ItemView
• Collection View
• Composite View
• Modules
• Messaging Bus
• Request
• Command
• Pub / Sub
New Toys
Messaging Bus
Controller
Entities
APPLICATION
USERS
LIST SHOW NEW
ENTITIES
USER NOTE
NOTES
LIST NEW
App Modules Shared Resources
Messaging Bus
Controller
Entities
## backbone/apps/users/list/[email protected] "UsersApp.List", (List, App, Backbone, Marionette, $, _) ->
class List.Controller extends App.Controllers.Base initialize: -> users = App.request "user:entities" ## ...remaining code...
## backbone/apps/entities/[email protected] "Entities", (Entities, App, Backbone, Marionette, $, _) ->
class User extends Entities.Model
class UsersCollection extends Entities.Collection model: User
App.reqres.setHandler "user:entities", -> users = new UsersCollection users.fetch() users
Messaging Bus
Controller
Entities
## backbone/apps/users/list/[email protected] "UsersApp.List", (List, App, Backbone, Marionette, $, _) ->
class List.Controller extends App.Controllers.Base initialize: -> users = App.request "user:entities" ## ...remaining code...
## backbone/apps/entities/[email protected] "Entities", (Entities, App, Backbone, Marionette, $, _) ->
class User extends Entities.Model
class UsersCollection extends Entities.Collection model: User
App.reqres.setHandler "user:entities", -> users = new UsersCollection users.fetch() users
Messaging Bus
Controller
Entities
Messaging Bus
Controller
Entities
Application
Folder Organization
backboneapp.js
Folder Organization
backboneapp.jsapps
Folder Organization
backboneapp.jsappsconfigentitiescomponentsmixinsbase
Folder Organization
backboneapp.js
configentitiescomponentsmixinsbase
playlist playlist_songs albumalbum_comments
currently_playing
apps
Folder Organization
backboneapp.js
configentitiescomponentsmixinsbase
playlist playlist_songs albumalbum_comments
currently_playing
apps
Playlist.List
Playlist.New
Playlist.Show
Playlist.Show
Playlist.Show
Playlist.Edit
PlaylistSongs.List
CurrentlyPlaying.Show
CurrentlyPlaying.List
CurrentlyPlaying.List
apps playlist
playlist_songs
listshow
currently_playing
playlist_app.js
editnew
listplaylist_songs_app.js
listcurrently_playing_app.js
show
apps playlist
playlist_songs
listshow
currently_playing
playlist_app.js
editnew
listplaylist_songs_app.js
listcurrently_playing_app.js
show
apps playlist
playlist_songs
listshow
currently_playing
playlist_app.js
editnew
listplaylist_songs_app.js
listcurrently_playing_app.js
show
apps playlist
playlist_songs
listshow
currently_playing
playlist_app.js
editnew
listplaylist_songs_app.js
listcurrently_playing_app.js
show
The End
@BackboneRailsBrian Mann