

Preventing memory leaks in Backbone.js - doctororange
https://paydirtapp.com/blog/backbone-in-practice-memory-management-and-event-bindings/

======
davidw
Ugh. Examples use Coffeescript instead of universally accessible Javascript.
Looks very useful though; I've just started learning about Backbone, and the
lack of a "right way of doing things" is disconcerting, coming from a lot of
Rails usage lately. It takes me back to the days of doing a lot of stuff by
hand.

Even without that uncertainty, it's definitely a bit tricky to move to
thinking about everything being in the browser.

~~~
throwa
@davidw, Just use emberjs and focus on your app instead of boilerplate code.
If you are coming from rails, emberjs is opinionated and should fit your style
of thinking.

Emberjs makes building non-trivial easy while backbone makes building non-
trivial apps hard but makes building small simple app easy.

People like talking about the size of emberjs but after you finishing
stitching together numerous boilerplate code, you might end up with a bigger
code base than emberjs and you are worst off as you have to maintain your
boilerplate yourself rather than use a community curated codebase.

Two good getting started tutorial: <http://trek.github.com/>
<http://emberjs.com/guides/router_primer/>

__Please i don't dislike backbonejs but we should use the right tool for the
right job, backbone is not the right tool for non trivial app except you like
boilerplate code. I also respect Jeremy Ashkenas. So my comments are not hate
induced.

~~~
atomical
Getting started with Ember is a lot harder than your comment admits. I tried
Ember recently and there was still a lot of stuff that was broken including
the data model. That would make building a non-trivial app hard.

~~~
davidw
What I'm investigating Backbone/Ember/whatever for is a semi-embedded device
that will ship with a web interface, so some semblance of stability is a major
plus.

~~~
throwa
As we speak it is used in production by many companies. Click this link to see
them all:

[https://github.com/emberjs/ember.js/wiki/Production-
Deployme...](https://github.com/emberjs/ember.js/wiki/Production-Deployments-
Page)

Shopitome is a very fresh deployment using emberjs based on this tweet sent
today:

<http://twitter.com/inkredabull/status/268017623428657153>

<http://www.shopittome.com/threads/signup>

A few non trivial companies using emberjs in production are:

www.zendesk.com

<http://www.squareup.com/>

<http://livingsocial.com/>

<http://www.groupon.com>

<http://www.desk.com/>

<http://basho.com/>

<http://travis-ci.org/>

<http://www.gooddata.com/>

~~~
davidw
Web production != shipping on devices production. You can very easily ship
updates to the former whereas the latter is tricky. It means we need to be
careful with everything we choose.

------
ldehaan
I agree on the whole coffeescript thing, really it detracts from what you are
trying to show. But on to the real point of commenting; I am implementing a
system using backbone because it is a requirement of the company I am
contracting for. I am writing several..plugins..I suppose you would call them,
to make backbone work more like angular.js. If you're having issues with
backbone and have a choice, I strongly recommend checking out angular. it is
quite amazing and very flexible. while it seems like it should be opinionated
it is actually quite flexible on what you must do once you learn how it works.
A great example is view compositioning, it has a very strong templating system
using definitions to create your own element sections. I am having a really
hard time liking backbone, if I have to write all this code, really I would
much rather write my own library to handle this stuff. So just my point of
view along with a suggestion on something that I believe can take you much
further and reduce the time you spend on the b.s.

------
Jacob4u2
I've been using chaplinjs as a backbone architecture for my last couple side
projects and I really like it.

<https://github.com/chaplinjs/chaplin>

Simplified router, subviews, model binding techniques like described in the OP
are all helpfully baked in.

------
mikeknoop
Two things you can do together to help, but need Backbone edge version
(master) for the second, at the moment:

    
    
      1. myModel.on('change:title', this.render, this); // inside `myView`
      2. myView.dispose(); // when you are done with `myView`
    

This will automatically remove all the referenced binds onto `myView` and
simply removing the root view as OP mentions is sufficient.

~~~
chrizel
But you have to keep in mind, according to the code
([https://github.com/documentcloud/backbone/blob/master/backbo...](https://github.com/documentcloud/backbone/blob/master/backbone.js#L1234)
) this will only get rid of the events on this.model and this.collection. If
you are using another field or model (like in your example myModel, if it is
not the same as this.model) -- then you will still get memory leaks.

Backbone is a real pitfall here in larger projects and you have to keep memory
leaks in mind when using Backbone events. (sadly JavaScript has no WeakMaps
yet, which would solve the problem for us) That's why projects like Backbone
Marionette or EventBinder exists which are handling the Backbone events
leaking problem better than bare bones Backbone alone. See
[http://lostechies.com/derickbailey/2011/09/15/zombies-run-
ma...](http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-
page-transitions-in-backbone-apps/)

In a very large application I'm writing at the moment I've introduced a common
View parent class which extends Backbone views with proper subview handling
and correct event disposal. So in my views I can write something like this
(works very similar to the Backbone view's DOM "event" mapping field, but
instead of DOM events we are talking about Backbone events here) [Edit: well,
looking at the submission article, that's very similar to the solution
described in the article]

    
    
        objectEvents: {
          'model change': 'reload',
          'collection reset': 'render'
        }
    

Then my View class handles the rest: it connects the events in the constructor
and disconnects them correctly on remove(). The only thing you have to keep in
mind is that you have to remove all old subviews explicitly when they get
recreated. That's when my subview handling kicks in, because I have some
helper methods like addSubView and removeAllSubViews which get called when re-
rendering the parent view.

Backbone subview handling can be a real pain and memory management has to be
kept in mind. Every time you are using the "on"-method you should ask yourself
when this event gets destroyed and if it could lead to a memory leak. Or you
should use something like EventBinder.
<https://github.com/marionettejs/backbone.eventbinder>

~~~
moe
_Backbone subview handling can be a real pain and memory management has to be
kept in mind._

Which is one of the main reasons why EmberJS was created.

Sometimes I wonder why backbone is still getting so much love when saner
alternatives (Ember, Angular etc.) have been around for so long.

Is it only inertia or is there perhaps a need for a framework in the
middleground between backbone and ember (in terms of abstraction)?

------
bjhoops1
Great pointing out that Backbone is _deceptively_ simple. No best practices to
be found on backbonejs.org.

Always worth considering using a framework layer like Marionette to help you
with architecture. Otherwise you _will_ end up writing something similar to it
yourself. Which sometimes is necessary, but not always.

------
EzGraphs
Javascript memory leaks can be identified using Browser Profiler (e.g.
[https://developers.google.com/chrome-developer-
tools/docs/he...](https://developers.google.com/chrome-developer-
tools/docs/heap-profiling)). Are there any other better/recommended tools for
the job?

~~~
chrisa
For IE specific memory leak testing, I've found sIEve to be very helpful:
<http://home.wanadoo.nl/jsrosman/>

------
SeppoErviala
Don't nested child views get garbage collected when the root view is removed?

~~~
jpk
If the parent is the only place where there's a reference to the child view,
then yes. However like the article says, you often have things like event
listeners that, if the child view doesn't clean up, will prevent the child
view from getting collected. (And often, the listeners still do stuff causing
buggy behavior.)

This is fixed by ensuring there's an off()/unbind() for every on()/bind(). I
do this by following a pattern like the one in this article:
[http://lostechies.com/derickbailey/2011/09/15/zombies-run-
ma...](http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-
page-transitions-in-backbone-apps/)

~~~
andrewvc
Yes, but if they are bound to the child's element and that is removed
shouldn't that be sufficient unless the view is binding to other elements or
window events?

~~~
m64253
It's quite common to bind to events on objects like models or collections etc.
which will not be unbound just because the dom element is.

~~~
Flow
Isn't that true only for older Internet Explorer versions because they had two
garbage collectors, one for DOM stuff and one for JScript stuff?

~~~
chrizel
That's not a problem just for IE. It's a problem that browser vendors could
only solve by giving us WeakMaps (which could come in ES6
[http://wiki.ecmascript.org/doku.php?id=harmony:weak_maps#wea...](http://wiki.ecmascript.org/doku.php?id=harmony:weak_maps#weakmap)
)...

The problem is, you have a bunch of subviews which are registering events on
some collection models... when you rerender your parent view your subviews get
recreated but your previously created subviews stay in memory because the
backbone events system still stores references to the old views which aren't
really needed anymore. The only solution is to explicitly remove the events
when subviews a destroyed (or better use a solution like in the submitted
article) or use a library like
<https://github.com/marionettejs/backbone.eventbinder>

------
politician
I highly recommend onsi's Backbone.coccyx [1] for ensuring that views are torn
down correctly.

<https://github.com/onsi/coccyx>

------
sontek
Backbone.Marionette is pretty good at solving a lot of these issues but this
is a great blog on how to do it yourself.

------
odiroot
AFAIR, it's one of the issues Backbone.Marionette is trying to fix with its
bindTo/close solution.

