Slide 1

Slide 1 text

Backbonification Migrating NewsBlur from DOM spaghetti to Backbone.js Samuel Clay November 2012 Backbone.js patterns and pitfalls — covering —

Slide 2

Slide 2 text

Background • Started NewsBlur as a side-project in 2009 • Open-source since the beginning • DocumentCloud alum

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Folder Feed Unread count Feed list header Feed list Unread count Reading pane Feed (story view) Story title Original/Feed view Intelligence Level

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Project Account Project List Organizer Visual Search Facet Facet input Workspace Toolbar Document List Document

Slide 9

Slide 9 text

Task at hand • Small handful of JavaScript files • 8,500 lines in biggest file • One file for templates, drawing, delegation, element caches, state, view modes

Slide 10

Slide 10 text

Performance • Only necessary calculations were made • Tree traversal time was eliminated 0 100 200 300 JavaScript Backbone.js feed page load (milliseconds) 0 325 650 975 1,300 JavaScript Backbone.js folder draw (milliseconds)

Slide 11

Slide 11 text

Pre-requisites • Underscore.js

Slide 12

Slide 12 text

Pre-requisites • Backbone.js Router Collection Model Model Model View View View Model

Slide 13

Slide 13 text

Moving routers • You have routers • Even multiple routers • If it touches a URL, use a router

Slide 14

Slide 14 text

Moving routers • It’s where you can stick those out-of- band ajax calls • Anything having to do with the url

Slide 15

Slide 15 text

Moving models

Slide 16

Slide 16 text

Moving models • The schema coming from the server • May cause versioning • Server should be sending lists of dictionaries

Slide 17

Slide 17 text

Moving models • Passing ?v=2 now gives arrays: • Data used to be given in this format:

Slide 18

Slide 18 text

Moving models • Transparently append the API version as a parameter by overriding your collection’s fetch method.

Slide 19

Slide 19 text

Moving models • Straight JavaScript object literals • Benefits: defaults and explicit behavior

Slide 20

Slide 20 text

Moving models • Pass a Backbone model's model.attributes to old JavaScript methods • When done migrating, clean up by looking for .attributes

Slide 21

Slide 21 text

Moving models • Populating a collection that has side-effects • Rendering child views before the parent view means they will be attached to the wrong parent view • Pass {silent: true} to the initial reset, then manually trigger the reset event with Collection.change() • Another option is to use _.defer()

Slide 22

Slide 22 text

Moving models • Listening for events on a collection's models • For convenience, model events also show as collection events

Slide 23

Slide 23 text

Moving models • Bind to the change event but only update on specific attributes using model.hasChanged() and model.previousAttributes()

Slide 24

Slide 24 text

Moving models • Listening to the change event instead of change:attribute because change is fired last

Slide 25

Slide 25 text

Moving models • Intermediary models can be used as pointers to selected models

Slide 26

Slide 26 text

Moving views

Slide 27

Slide 27 text

Moving views • Writing templates

Slide 28

Slide 28 text

Moving views • Template option #1: Inline strings

Slide 29

Slide 29 text

Moving views • Template option #2: Inline templates

Slide 30

Slide 30 text

Moving views • Template option #3: JavaScript Templates (JSTs)

Slide 31

Slide 31 text

Moving views • Most common change is from event binding to event delegation

Slide 32

Slide 32 text

Moving views • Splitting up views for the same element

Slide 33

Slide 33 text

Moving views • Changing the top-level element of a view • But don’t forget about the element on page if you’re re-rendering the view

Slide 34

Slide 34 text

Folder view Folder view Folder view

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

Moving views • View collections

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

Moving views • Traversing a view by keeping track of the active view in the collection

Slide 42

Slide 42 text

Moving views • Action hierarchy • Delegate responsibility up the chain

Slide 43

Slide 43 text

Moving views • No need for a model to back a view

Slide 44

Slide 44 text

Common pitfalls

Slide 45

Slide 45 text

Common pitfalls • TypeError: 'undefined' is not an object (evaluating 'func.bind') • Comes from trying to bind to a method that doesn't exist

Slide 46

Slide 46 text

Common pitfalls • Firing a change event while still setting up models and views • Add {silent: true} to a model.set() call if you're not ready to handle the change events • When views are all setup, blast out a .change()

Slide 47

Slide 47 text

Common pitfalls • Re-rendering the view just to get a class toggled on or off • Selectively re-render/toggle classes based on specific change events

Slide 48

Slide 48 text

Common pitfalls • Cleanup of ghost views • The model still has bindings to the destroyed view

Slide 49

Slide 49 text

Common pitfalls • The disappearing view

Slide 50

Slide 50 text

Resources that I liked • Developing Backbone.js Applications by Addy Osmani addyosmani.github.com/backbone-fundamentals • Backbone Patterns by Rico Sta. Cruz ricostacruz.com/backbone-patterns

Slide 51

Slide 51 text

Thank you for listening • Go ask @samuelclay more questions • Get yourself on www.newsblur.com