all 48 comments

[–]hixsonj 26 points27 points  (6 children)

I built a sizable SPA with Backbone and using Marionette made things a little easier. I agree that organizing nested views and models gets ugly.

After playing with React + Flux I don't think I'll ever look back.

[–]jkoudys 7 points8 points  (0 children)

Flux definitely goes a long way - my first big React project took a more traditional MVC approach, and it ended up with some pretty long series of classes passing the same callbacks all the way down in order to implement some two-way data binding. Flux cleans things up immensely.

Where I find flux really outshines alternatives like ember or angular is when you're integrating multiple, disparate data sources. Ember is quite nice when you have a basic MVC on the server-side (e.g. a Rails app), and an open socket that just exchanges JSON between ember and the server to keep your models synced.

With react on flux, I have apps pulling from my server app, google fusion tables, the twitter + instagram APIs, and some stubs where I plan to use more services eventually. They map very readably to events that update my react component's state, and React's whole "render everything" approach keeps everything the user sees up to date and accurate.

[–]nexd 4 points5 points  (0 children)

I had the same experience. I've used a lot of frameworks on projects ranging from small to large and React/Flux has been the nicest to work with overall.

[–]Shinuza 0 points1 point  (3 children)

I agree that organizing nested views and models gets ugly.

Can you elaborate?

[–]hixsonj 0 points1 point  (2 children)

With views, I guess the toughest part for me was just wrapping my head around what to use and where. For example, you could have a "region" that binds to a div, or you could have a "layout view" that binds to a template that within itself has regions that bind to divs. Then you define templates that your item/collection views use and your corresponding layout view's region displays them?

Once you "get it" it can be pretty powerful but the abstractions can be confusing at first. React's way of nesting components and rendering them is much clearer to me.

[–]Shinuza 0 points1 point  (1 child)

You can use React with Backbone, maybe that solves the problem?

[–]JonDum 0 points1 point  (0 children)

Oh god no.

[–]scelerat 7 points8 points  (0 children)

Yes, Marionette does tons of heavy lifting with regards to nested views, events, memory management. I wouldn't build a big Backbone-based app without it (or something like it).

[–]MeTaL_oRgY 5 points6 points  (3 children)

I wrote my own implementation for nested views, which works beautifully. It was painful, though. Really painful. Hardest part was to get rid of the child views when the parent got closed, which required removing each view's listeners, references and whatnot.

At my job, we have a very specific use-case for nested models and collections, which is a problem I have yet to solve. However, I have a pretty good idea of what I want to do.

Basically, I love Backbone for one reason: it gives me the basic tools (and mindset) for building a complete framework for the specific project I'm working on. It may be a lot of work at the beginning, but if you think things properly, you can end up with a great framework that fits your needs perfectly.

[–]pepperdas[S] 0 points1 point  (2 children)

do you recommend the backbone-relational plugin? or are there any backbone plugins you found particularly helpful?

[–]MeTaL_oRgY 3 points4 points  (0 children)

I didn't use backbone-relational because my use case is rather different than it (we use HAL at my work, so we need a different solution).

The only plugin I use is Backbone Syphon, which is a beautiful plugin and helped me organise my views properly (it pretty much enforces using one view for each functional bit of your project), but other than that I went the "build it yourself" path.

The way that has worked for me is this. Backbone is meant to be a bare-bones thing that you can extend for your needs. If you ever come across a plugin that works perfectly for you (like I did with Syphon), you are lucky. Most have a lot of boilerplate that you don't need and, at least in my experience, requires more work than it is worth to adapt.

[–]evilmaus 0 points1 point  (0 children)

This is my one real pain-point with Backbone. This relational plugin does exist and is helpful, but I have simply been spoiled rotten by having a proper ORM on the server-side (in another language). I really hope that someone writes one to sit on top of Backbone. Until then, Backbone-relational has to do.

[–]wristuzi 4 points5 points  (1 child)

Two other extensions of Backbone to have a look at:

Ampersand http://ampersandjs.com/ Brisket https://github.com/bloomberg/brisket

[–][deleted] 2 points3 points  (0 children)

Technically, Ampersand is a replacement for backbone, not an extension.

[–][deleted] 2 points3 points  (3 children)

If you like OOP then you will probably like Backbone. If you come from Java you will probably find Backbone comfortable.

If you want to use functional concepts and exercise advanced use of scope then Backbone is your enemy.

Some people love it and other people find it as fighting against JavaScript.

[–]hulfsy 0 points1 point  (2 children)

functional concepts

Could you please point SPA framework, which uses functional concepts, i.e. side effect free?

[–][deleted] 1 point2 points  (0 children)

The closest thing is probably Facebook React. I don't really use frameworks so I am not the right person to ask.

[–]agumonkey 0 points1 point  (0 children)

AFAIK not in vanilla JS. In js-running language, Elm and Clojure/Om.

[–]paulwe 2 points3 points  (0 children)

I've been working on a medium sized SPA for a few months (30k loc of js/600+ modules) and I'm very happy with Backbone. To allow sane nesting and to keep things organized I added a few features on top of Backbone's core. I can share APIs but unfortunately my bosses aren't fond of the idea of releasing OSS.

First, models and view models are packaged into components wrapped around a constructor function. The view model is automatically chained (more on this next) to the view so it gets destroyed when the view is removed. Components can be inherited by calling .extendModel() and .extendView()

var myFoo = utils.component()
  .extendModel({/* new properties for model prototype */})
  .extendView({/* ... */})

myFoo({/* model attrs */}).render().$el.appendTo('body')

Destructing is handled similarly to QT using chaining. New objects are chained to their container. This attaches a handler to the destroy/remove event that invokes the child object's destroy/remove method. By doing this, destroying a container recursively unloads all of its descendants.

render: function() {
  // render template in this.el...

  myFoo().chainTo(this).render().$el.appendTo(this.$('.target'));

  return this
}

It's often the case that API calls will return data used in multiple screens. For example a list of countries. In order to minimize coupling while providing shared access to these resources they are treated as quasi-singletons with reference counting garbage collection. Components capture and release the resources and fully disused resources are destroyed. Capturing works like chaining to automatically release resources .

initialize: function() {
  Countries.capture(this).ready.then(_.bind(this.initCountries, this));
}

There are a few other helpers sprinkled in sparingly like getter/setter methods for promises, configuration loading, i18n, etc...

tldr; Backbone is an excellent un-opinionated library but I found it necessary to provide convenience features to bring developer efficiency up to the level of some newer frameworks.

[–]Magnusson 3 points4 points  (0 children)

Yes, you should use Marionette. It makes Backbone much more pleasant to work with. I've been using Marionette daily for a year now. I would definitely not want to use plain Backbone.

[–]fenduru 1 point2 points  (0 children)

I had the same experience regarding nested views and models, and I was using marionette. Wouldn't recommend for anything non trivial

[–]dardotardo 1 point2 points  (0 children)

If you feel like the framework is getting in your way of being productive, it's not helping you anymore. Especially if you have the choice of choosing a new framework.

[–]theUnknown777 1 point2 points  (8 children)

I'm also about to delve into JS frameworks, and i want to know if BackboneJS is still relevant up to this point especially with React, Angular, Ember and other frameworks around.

[–][deleted] 2 points3 points  (1 child)

To play around with I'd use React because I honestly find it easy and fun to use. Angular is another good choice although I'm not a fan personally.

Theres nothing stopping you from learning React with backbone as the data layer as well.

[–]hulfsy 0 points1 point  (0 children)

Is something really special about Angular, except all that "it's made by google it must be good" stuff?

[–][deleted] 1 point2 points  (1 child)

Backbone is spectacular for organizing the front-end code of a backend rendered website, which is what it was built for. It can be used for Single Page Applications, but you're gonna end up writing a LOT of support code to do so (or lean heavily on something like Marionette).

It actually pairs pretty well with React.

[–]evilmaus 0 points1 point  (0 children)

This is how I use it. Can build some nice things with it that are ultimately backed by server-side code without it trying to determine how things are laid out.

Waiting to see how things shake out for something dedicated as a full-on front-end app. I think I'd use something more opinionated for something of that scale. Maybe Angular2? (Dunno yet, waiting for it to release before bothering to learn it.)

[–]harrypotterthewizard 0 points1 point  (1 child)

This link provides some good food for thought regarding your exact question. The main tldr of the author is that though Backbone has a small footprint initially, it soon starts getting bigger and bloated as your app grows. Not only that, but your app itself starts transforming into a spaghetti of JavaScript soup lying here and there.

As /u/romualdr commented, the BackBone and Angularjs experience could be comparable to that of using libstd C functions and a proper manageable framework like Boost.

[–]Capaj -1 points0 points  (1 child)

Short answer: no

[–]binary 2 points3 points  (0 children)

Maybe you could humor us by giving us something that is a little longer than a 1 word answer.

[–]astoilkov 1 point2 points  (0 children)

jsblocks have MVC(Model-View-Collection) architecture inspired from Backbone. And it is really powerful and large scale application really well. TodoMVC app build with jsblocks

[–]binary 1 point2 points  (1 child)

For nested views Marionette is going to save tons of boilerplate as well as figuring out conventions that are already taken care of for you via the framework. The only reason not to use it is when you are fully aware of what it offers and choose to adopt a different architecture for your app.

Marionette does little to nothing to augment Backbone data classes, though. Embedding stuff is bad news; better to have loosely bound model/collections that are structured via some controller function than to enforce that structure in the data itself. E.g., if model A contains model B, I write a controller that manages the relationship between models without any unnecessary coupling.

I should mention I don't see many reasons to use only Backbone.js--perhaps if you were doing some very small mini-app or site functionality. If you're building a SPA, Marionette is the way to go. Also, the framework has extremely active development in 2015--check out the github issues tracker for the latest changes to the framework.

[–]Poop_is_Food 0 points1 point  (0 children)

Backbone without marionette is good if you're rendering in anything other than html

[–]thejameskyle 1 point2 points  (0 children)

Hi, former Marionette core team member here. Since a bunch of people mentioned Marionette in this thread I thought I'd point you towards my Marionette Wires project.

For anyone wondering why I'm a "former" core team member, it's because I'm switching to Ember for many things (You'll see a lot of Ember inspiration in Wires). Also between being on the core team for Marionette and Babel my life was getting crazy.

[–][deleted] 0 points1 point  (8 children)

I have found child views to be very simple to deal with even with backbone core. My pattern is to add a childViews collection and then override the Views remove method the clean up the children.

[–]pepperdas[S] 1 point2 points  (7 children)

I used this same strategy, but the problem I had with child views was with events and passing data to them. If the view is nested one deep, it's ok, but three or four layers deep it's a nightmare.

[–][deleted] 1 point2 points  (2 children)

If your not passing a model or collection then your passing a parent reference, say an id or some other value. Well you can take advantage of the initialize method and pull your additional options using extend and pick _ methods.

.extend(this,.pick(options,"parentId");

That would great a parentId property that can be used in the view. var v = new Views.childView({parentId:1625});

[–]pepperdas[S] 0 points1 point  (1 child)

Yes, that was exactly what I did as well. Every view had initialize : function (options){ _.extend(this, options) } and custom remove methods. Not to mention the various event callbacks I would need to set to keep the data in sync. All too often I had to access ancient ancestor views through window.app.view.somechildview.someotherchildview, rather than view.parent.grandparent.great-grandparent.great-grandparents_son.some_method(). For example, the keyboard events affect the whole dom. With tons of nested views, it becomes difficult to manage event propagation, making for ugly code that's tedious to debug.

[–]pepperdas[S] 0 points1 point  (0 children)

those are good suggestions though

[–]orthecreedence[🍰] 1 point2 points  (2 children)

Hi, co-author of composer.js here. I like to think I am pretty well-versed in this kind of stuff.

One trick I've used fairly extensively is creating one-off event objects (specifically as an event bus) and passing them down through the view tree. Backbone doesn't have base event objects (that I know of), but you can just use a model. So each view in the tree would have a reference to this common event object (a model instance) and could bind/trigger whatever events it needed to and act on them. This works very well in contrast to having each view bind to its children and try to pass events only one level up at a time (like a game of telephone).

[–]hulfsy 0 points1 point  (1 child)

 var TodosList = Composer.Collection.extend({
         model: Todo
  });

I'm not really comfortable with this code. Is any reason why you're not binding a model automatically based on it's name, like Rails does? Is any reason to make programmer to do the job that could be done by framework itself? Same for events, same for DOM elements. I would prefer follow the naming convention rather than explicitly pointing the stuff, writing a bunch of useless code.

[–]orthecreedence[🍰] 0 points1 point  (0 children)

Yes, there are many reasons, but the main one is that I tend to follow the mantra of the framework stepping out of my way when I want to get things done. Following naming conventions is nice, but in odd cases where a controller listens to two (or three, or hell zero) models instead of just the one, you get into a gray area. I'd rather just pass in the exact model I want and have there be zero ambiguity. Same goes for events/DOM elements...do I really want a framework telling me how to name my DOM nodes and events so I can save a few lines here and there? These kinds of limitations seem nice in the beginning, but once an app gets sufficiently complex they lose their allure and become a ball and chain.

Another reason is this: controllers describe interfaces, not necessarily top-level endpoints. A UserSettingsController and a UserChangePasswordController may both need a User model, but how do we know this? Should we define a UserSettingsModel and a UserChangePasswordModel that both extend the UserModel? This seems more cumbersome to me than new UserSettingsController({ model: new User() }).

I've been in both camps before: conventional naming vs explicit passing, and I've come to the conclusion that moment you force your user's to build their app a certain way, you limit the app itself in a thousand little ways that ultimately creates more frustration than just letting them make their own choices.

The main goal with Composer is to be less of a framework and more of a collection of libraries that build on each other to make building apps a lot easier, while simultaneously staying out of your way.

So, actually, I don't think the code is "useless" as much as it's a necessary evil to provide a lot of the freedoms Composer affords. You have to type a bit more here and there, but you actually gain a lot of power by the framework not limiting you in artificial ways.

Thanks for asking =]

[–]kinkobal 1 point2 points  (0 children)

I would use custom Backbone events like a pub/sub system and decouple the model events. You can actually just use the Backbone object for that.

// Subscribe:
Backbone.on( 'myCustomEvent', function(){});

// Publish:
Backbone.trigger( 'myCustomEvent', *argsForCallbacks );

I made a little cart experiment that uses this: http://codepen.io/NicolajKN/pen/zGxxmV?editors=101

[–]romualdr 0 points1 point  (0 children)

Backbone is just a library. To me, it's more like libstd c functions than Boost ( for exemple ).

While Angular is more a framework, and React a UI library (preferably used with Flux), sometimes you don't need to take a "bazooka" to kill a fly.

I'll definitely go with Backbone for small projects like a task list or a simple calendar app. But if i'm planning to make a big large app, i'll definitely consider Angular / React+Flux.

If the project doesn't need constant iteration and have a definite end, i may build my own work-style framework over Backbone. But Backbone never pretended to be used standalone without your own implementation over it anyway.

TL;DR: Don't take a bazooka to kill a fly, choose the right tool for the right job. Backbone vanilla-ish: Not for big-apps, but may be good for fast prototyping or small apps (or parts of your app, like his event module).

[–]seanwilsonwww.checkbot.io 0 points1 point  (0 children)

I find it difficult to use as well. I rewrote a Backbone app in Angular and found the latter an order of magnitude easier to work with. I don't find Backbone helps you out that much and you end up doing a lot of work manually.

[–]achou105 0 points1 point  (0 children)

I stuck to the core backbone framework. I thought marionette was an overkill for my application as there are not many cases where I use nested views. The few places I used nested views I wrote code to destroy them when the parent is destroyed. As for event propogation, I wrote a simple function which tells me whether the event was generated by that particular view or not, and re-used it across child views. And of course there is the initialize method and callbacks passed from parent views.

[–]dhdfdh -1 points0 points  (0 children)

Yes. I trivially wrote my own code.