

Backbone.js localStorage + remote sync - lucian1900
https://github.com/lucian1900/Backbone.dualStorage
We needed to use localStorage as a cache for a project, so we forked Backbone.localStorage (https://github.com/jeromegn/Backbone.localStorage)
======
jguimont
I think the "remote sync" label is misleading. It will sync properly if the
remote host is accessible. If you create something offline, it will never sync
it back to the remote host when the connectivity is restored. It will stay
local and might lead to problems down the road (when updating a locally
created record, the remote host will not know about it)

~~~
lucian1900
It will only sync it when connectivity is restored if explicitly done so, yes.

Atm our users trigger syncs manually, but we're planning to move to PhoneGap
network events as triggers for syncs.

------
avolcano
Oh, wow! This is awesome; I'm _just_ now at the point in a Backbone project
where I was preparing to implement something similar, and wasn't exactly
relishing the thought. It's awesome that I now have something to work with
instead of having to roll my own.

I do have one suggestion, though: while it's of course not much work to
compile the script to JavaScript, it couldn't hurt to include a current JS
version in the repo for people who don't have Node & CoffeeScript installed.

~~~
lucian1900
Good point, added.

~~~
iusable
Thank you, I was about to ask for the same!

------
scosman
I wrote something very similar a week ago:
<https://github.com/scosman/Backbone.CachedModel>

Differences:

\- it works with any .sync implementation you might already have (JSON, XML,
whatever). It just drops in, caching the server responses locally, not
assuming anything about how the service works

\- instead of overridding Backbone.Sync I let you extend CachedModel on a per
model basis (that way some models can be cached locally while others are not)

I didn't include any fancy cache expiry, just using a simple
localstorage.clear on login for now.

example usage: var User = Backbone.CachedModel.extend({ cacheName: 'USERS',
});

~~~
lucian1900
Interesting. I may steal some code :)

I handle not sending models to the server with remote/local boolean attributes
on the model. Certainly not as well decoupled as yours.

~~~
scosman
another thing to consider, Store.records is keeping everything in memory.
Using only localstorage should save some memory (although it depends on the
browser implementation)

~~~
lucian1900
Good point. On the other hand, localStorage access appears to block, sometimes
quite a bit. I'll investigate some more.

It's a bit I inherited from Backbone.localStorage, and haven't looked into
much.

------
jashkenas
Fun stuff. What's the strategy for shared models?

If I make changes based on a model that I've read from my local cache ...
while someone else edits the same model on the server ... how does that
reconcile when I try later on to make a change?

~~~
silverlight
I've started using ShareJS[1] in a new app recently to handle real-time
collaboration where conflicts are likely. It's spearheaded by an ex-Google
Wave engineer and uses Operational Transformation principles to handle
automatic merges.

I've been thinking for a little bit now that it would awesome to build a
Backbone sync system that could cache things locally when the user is offline,
then seamlessly handle bringing them back in sync with ShareJS.

[1] <https://github.com/josephg/ShareJS>

~~~
fooandbarify
This is intriguing. I've spent a bit of time building Backbone projects that
sync with the server (eg. <https://github.com/napoleond/localModel>) but until
now have always resolved conflicts by choosing the model with the most recent
time modified. (I have also played a bit with using WebSockets to keep the
models up to date for every concurrent user, although that was mostly just for
fun.) It would be way better to actually merge diffs in an intelligent manner,
though. Thanks for the link!

------
highpixels
Just what we needed! We were just planning on adding similar functionality
into our Backbone app. I check Hacker News an hour later, and there it is!

Looking forward to seeing the offline sync helper you mentioned in another
thread.

------
fooandbarify
Very cool. I wrote something similar a while back:
<https://github.com/napoleond/localModel>

My implementation leaves a lot to be desired with regards to re-use (there are
certain project requirements which happened to be met by the project I built
it for) but it does nicely manage automatic replication of the most recent
version of models between server and client.

As far as I can tell, this implementation reads from the local model if it
exists, otherwise it loads from the server? And writes always go to the server
unless explicitly told otherwise?

~~~
lucian1900
Writes always go both locally and to the server unless told otherwise, yes.

------
overshard
This is great, I love web interfaces that are completely async where you can
do whatever you want in realtime and it "magically" gets stored on the server
for me later.

This just makes loading up a page even faster as the data is more than likely
already on your computer.

Will this work for offline? If someone views a todolist, makes some changes
offline, then visits it later online will it sync the changes automatically?

~~~
lucian1900
Not entirely automatically. The app would have to explicitly sync the model
when it believes it can.

I do plan to add a helper for that, that keeps a list of unsynced models. Then
a function could be called when the server is reachable, or just periodically.

~~~
iusable
This helper + the PhoneGap network event monitoring would make this
indispensable for a bunch of projects. I know I would love it. Anyway I can
'tip' your work?

~~~
lucian1900
I've done this on company time so far, since we're using it for a product and
atm I wouldn't have enough free time to work on it otherwise.

We're going to release soon, so in the next few weeks I'm likely to add dirty
model syncing.

------
kylebrown
Another one here, have been procrastinating adding this capability for a week
now.

Now I just need to find (or write) some php code that will save/serve the
fetched json model.

------
drumdance
This sounds cool. Does the local storage extend to collections? Can I query
for locally stored objects? (i.e. created or updated within a given date
range)

~~~
lucian1900
It does work with collections, and it tries to reuse the cache if you first
get a model independently and then through its collection.

There's no specific local querying beyond listing window.localStorage.

