

Backbone.js and Chrome Extensions - mikeknoop
https://zapier.com/blog/2012/02/23/backbonejs-within-chrome-extension/

======
jaredsohn
Instead of caching the model in LocalStorage, couldn't you also just store it
in the extension's background page? You would simply store the data that you
would otherwise put in LocalStorage within a variable on the background page.
From the popup, you can access background page variables as members of the
object returned by calling chrome.extension.getBackgroundPage().

The extension would still need to recompute it once every time it is starts
up, but since it is computable I don't think it belongs in LocalStorage. (You
wouldn't store something like this in the registry if you were writing a
Windows program; you'd just keep it in memory.)

Also, the article could use a bit of improvement in terminology. When it talks
about 'loading the extension', it really means displaying the popup. I think
of loading the extension as in starting up the background page via the
extensions window.

~~~
mikeknoop
Good point I'll see if I can clear up that terminology in the post.

You are also correct that you could use the background page as an alternative
persistance layer instead of LocalStorage. LocalStorage is obviously more
applicable in non-extension environments. Is there a big benefit to using
background pages in a Chrome Extension over LocalStorage simply for storage?

One thought for future work: load the Backbone app into the background page
when the browser starts. Whenever the popup loads, simply update the Viewport
view's element with Viewport.setElement() to be the root popup body element.
This might allow persistance between popup loads.

~~~
jaredsohn
The benefit isn't that big.

From the standpoint of writing quality code, I think it is better to use the
background page instead of LocalStorage in that it lets you avoid writing to
disk (which requires space and has worse performance than using memory,
although at this scale the difference is trivial) and doesn't pollute your
LocalStorage namespace as much.

An advantage of the LocalStorage approach is your readers can write code in a
way similar to how they would if you were not writing an extension and it
makes the material more accessible in that it requires less understanding of
how Chrome extensions work.

~~~
jdavid
two points

-localStorage works on the background.html page

-when content scripts access localStorage, they do so at the domain level of the url

~~~
jaredsohn
I don't understand the purpose of your points here.

* localStorage also works from the popup (using the same storage as the background; that's how the tutorial was able to work).

* We're trying to get data working in the popup here, so how localStorage works in the contentscripts is irrelevant for solving this problem.

------
jfi
Nice post! For anyone interested in seeing another sample, I wrote a chrome
extension that leverages backbone as well a few months back:
<https://github.com/jeffreyiacono/penalty-blox>

~~~
mikeknoop
Very well done, it seems I was beat to the punch (updating the article
now...).

I'm curious, did you do anything special to work around fresh API hits each
time the popup is loaded (ie. LocalStorage)?

~~~
jfi
All data (account names and hash tags to remove) are stored client side in
localstorage, so the extension doesn't query / load data from an external API
like yours does. As a result, I haven't bumped into that "gotcha" yet. I do
use a background page to bridge the popup's stored data with the content
script that does all the heavy lifting (from what I remember). Just fyi on the
localstorage adapter: leveraging the one from the Todo example on the backbone
website. Thanks for giving me a shout out in your article, very kind of you.

~~~
mikeknoop
I have another comment on this thread with an idea for future work
(<http://news.ycombinator.com/item?id=3631097>). I'd be curious to know if
leveraging background pages for containing the Backbone instance would be a
clean way to handle persistence (of the entire app, not just data).

Have you ever looked at something like this?

------
mikeknoop
Author here, happy to answer any questions about the approach or code!

~~~
Keithamus
I think Backbone JS might be useful for facilitating communication between the
different components that Chrome uses (ie. contentscript <-> browser button).
I can't see anything in the Gists you provided that highlight this. Did you do
any work on this at all, where you could shed any light?

~~~
mikeknoop
I can explain a little more clearly on how Chrome generates the popup which is
shown in the screenshot (you may know this already).

When you define a browser_action inside your manifest.json file:

    
    
       "browser_action": {
          "default_icon": "icon_16.png",
          "popup": "popup.html"
       },
    

Chrome automatically places an icon in the top bar, and when clicked, loads
popup.html into a generated bubble.

Now, our foray into Chrome Extensions pretty much ends there. We load all our
Backbone code via popup.html and let it do its thing. We did not look at any
other of the mechanisms Chrome provides to extensions such as contentscripts.

With that said, I also see a lot of value in leveraging Backbone's Model and
Bindings within contentscripts and it would be something worth exploring --
but it wasn't directly applicable to understanding how Backbone could work for
us in overhauling our frontend.

~~~
troyk
I was just reading through the docs and am getting ready to write my first
extension and think I'm going to try and get backbone running in the content
script where I believe it's state will be persisted through open/close of the
popup.

Thanks for your post!

~~~
mikeknoop
To be clear, a contentscript is a script which runs only on a specific website
or domain (for example, if I specified my contentscript to run on zapier.com,
it would get loaded every time I access that page).

Popups, on the other hand, get their scripts loaded into a brand new document
when the icon is clicked and rendered into the popup bubble.

Backbone makes model/collection caching very easy so my preferred method would
be to override Backbone.sync to store data inside LocalStorage.

There are a few blog posts out there with tricks on how to persist state
between popup loads (unloading the popup DOM into the background page...). I
think these strategies would break a Backbone app due to how view bindings
work. I'd be curious to know any other ideas on how to persist the actual
state (and not just model/collection data) between popup loads.

EDIT: To answer my own question a little bit, you could probably get fancy
with
[http://code.google.com/chrome/extensions/background_pages.ht...](http://code.google.com/chrome/extensions/background_pages.html)
but I'd need to do more research on the relation between background pages and
popups.

~~~
troyk
If you find a way to persist the popup please share, I spent the last 9 hours
in all out battle. Basically chrome shit cans the window object on blur, the
closest I came was pushing the popup body into the background page for
resurrection later, but it's clunky around the edges as your dealing with a
new window/document context so stuff like js context, scroll position, etc.

I've tabled it for now. I'm 99% sure the way to go is to put a popout link on
the popup, setPopup to null and then bind the click listener for the popup
icon to focus the popup. If the user closes the popped out popup reset
setPopup and the process starts anew. I'll still be overring backbone sync and
keeping all the data in the background.

------
indubitably
Oh, I've got an idea: now that we're approaching a world where cross-browser
shit works, let's take the tech that is designed to build on top of that and
use it to build shit that doesn't work cross-browser.

~~~
jdavid
maybe the world is big enough now for multiple internets

------
platz
I believe <https://github.com/oo7ph/Trello-Clone> another chrome extension,
uses backbone as well. But I haven't studied this one (yet).

