Hacker News new | past | comments | ask | show | jobs | submit login
Announcing Backbone.js 1.0 (ashkenas.com)
396 points by jashkenas on March 20, 2013 | hide | past | favorite | 64 comments



The change log for 1.0 can be found here: http://backbonejs.org/#changelog

1.0.0 — March 20, 2013

* Renamed Collection's "update" to set, for parallelism with the similar model.set(), and contrast with reset. It's now the default updating mechanism after a fetch. If you'd like to continue using "reset", pass {reset: true}.

* Your route handlers will now receive their URL parameters pre-decoded.

* Added listenToOnce as the analogue of once.

* Added the findWhere method to Collections, similar to where.

* Added the keys, values, pairs, invert, pick, and omit Underscore.js methods to Backbone Models.

* The routes in a Router's route map may now be function literals, instead of references to methods, if you like.

* url and urlRoot properties may now be passed as options when instantiating a new Model.

Congratulations to Jeremy and everyone else who made this milestone possible. We've come a long way in the JS community over the last few years since SproutCore & Cappuccino were all the rage - Backbone has undeniably been a huge part of the progress we've seen.


SproutCore and Cappuccino have also undeniably been a huge part of the progress we've seen ;)

To expand on your helpful paste, for the detail-oriented among you, the full list of changes and diff is available here: https://github.com/documentcloud/backbone/compare/0.9.10...1...


Cappucino is great , its problem is that it is just not debuggable for now , but maybe one day when it gets source maps. Otherwise it is a great framework.

Backbone is great because it is minimal , you can start small then grow with it , like sinatra ,etc .... i like that approach.


When I first worked with Backbone.js almost a year and a half ago, honestly, me and my team hardly had any clue what we were doing; the documentation was probably just as good as it is today, but it just didn't click with us, it seems. We did finish our application at the time (a six-screen monitoring application, think a lot of tables and some graphs), but it didn't feel "nice".

A year ago we started our second project, and it made a lot more sense. It's a pretty big project, we've got ~10.000 LOC of Javascript, most of which is Backbone views/models/routers, some Handlebars helpers. The project has, based on our filenaming conventions, 18 routers, 68 views, and probably around 75+ models. Using Require.js we keep the codebase clean and organized, and using some custom functions (a close function, most importantly) we stop it from being a memory hog.

I like Backbone. The major competitor is Angular, but it's more high-level; Backbone itself is just a thin layer on top of vanilla JS, jquery and underscore, really, but that's what gives it its power.

Looking forward to upgrading to 1.0. The change in reset behavior will cost us some work, but it sounds like it's doable.


Not to rain on Backbone's parade, but I am easily twice as productive in angular.js. The learning curve is a bit steeper but once you mastered you end up with (IMO) a cleaner more maintainable app.


The coupling between views and controllers - at least based on the examples on the front page - looks horrible to me, and makes it a non-starter right out of the gate. To me that feels like a return to the bad old days when we embedded PHP right in the HTML....


If Angular doesn't float your boat, that's fine. For those wondering if this is true, it's not. Views in Angular can interrogate their controller for model data, and they can fire events into the controller. The controller doesn't know about the view (or even if it is hooked up to a DOM instead of a test runner). You can reuse a view with a different controller (provided, of course, the controller supports the same operations). I don't believe that this level of coupling is harmful. In fact I think it separates these concerns nicely.

The view is written in HTML, you declare the bindings with moustache-style templates or with attributes. Some people get really hung up on this, but the declarative UI is not Turing complete, so it's not really like embedding PHP at all.

By the way, I like Backbone too, and I use Underscore everywhere. Congratulations to all involved on reaching an important milestone and creating tons of value for everybody.


> You can reuse a view with a different controller

Then the examples on the site are really misleading, given that they hardcode the controller name in the example views.

EDIT:

To give an example of what I object to, this is cut and pasted from the Angular homepage:

    <div ng-controller="TodoCtrl">
      <span>{{remaining()}} of {{todos.length}} remaining</span>
      [ <a href="" ng-click="archive()">archive</a> ]
      <ul class="unstyled">
        <li ng-repeat="todo in todos">
          <input type="checkbox" ng-model="todo.done">
          <span class="done-{{todo.done}}">{{todo.text}}</span>
        </li>
      </ul>
      <form ng-submit="addTodo()">
        <input type="text" ng-model="todoText"  size="30"
               placeholder="add new todo here">
        <input class="btn-primary" type="submit" value="add">
      </form>
    </div>
First, it hardcodes the controller name. This, to me is configuration information - part of setting up routes - that the view should not know. Then there's the ng-click and ng-submit bits. More configuration that I really don't want in my views. It also seems to declare the model to update in the view?

This is what I meant about tight coupling to the views.


Good questions. I fully support DOM Spaghetti Aversion, but Angular's approach is quite different from PHP. I'd hate for people to dismiss it because they heard its the new PHP or because it cosmetically resembles an anti-pattern.

To answer your specific concerns, you can in fact imperatively bind Angular controllers to route views in the app's configuration block. However, this approach doesn't always make sense—you can have multiple apps in a page, each app having multiple controllers, so they can't all use the URL as the engine of application state. In cases like this you can your view as a directive, and then you can inject the appropriate controller (in fact this is exactly how ng-view works with the router).

Or, you can take the approach quoted above, and use an XML-like declarative configuration language to describe the view and its relationship to whatever happens to be its controller, and let the compiler generate the appropriate HTML for you. (I'm kidding, it's HTML all the way. But in Angular, the view describes its own structure, appearance and behavior, the controller is concerned with mutating state and not DOM manipulation.)

I'm not trying to evangelize, just put some good information out there. Backbone's templates, as I recall, use ERB-style syntax to push values and imperative code into templates, which then set up their models (http://backbonejs.org/#FAQ-bootstrap). I think you agree it would be unfair to put down Backbone as the new PHP based on that fact that its templates let you write in that style.

Enjoy!


You know, it's really nice to work with. I like the structure Angular provides, but I tend to agree. It doesn't feel entirely "right". Maybe I just need to get over it.


How big is your Angular project? I mean I like the idea behind Angular, but my concern how Angular holds up in a huge app, let's say if Angular was written as the client of WordPress (or some blog) admin. I don't have enough experience with it to be able to judge how well it is to handle that.

Or would it be a hybrid of Backbone + Angular?

Would love to hear the opinion of someone more experienced.


The common anecdote is that Google used Angular to make the the Doubleclick advertiser interface, which is just as big if not bigger than the Wordpress admin interface. It turned out to be great, with much less lines of code than what they had before (GWT).

Regarding Backbone + Angular in a large project, I wouldn't touch that code base with a 10 foot stick.


Great thanks. My perception up until this comment was that Angular was more of a mini-tool for MVVM for use in little widgets, and not really able to be huge.

I wish it was advertised more what large projects using Angular and that they are actually architected completely with Angular.


I'm not sure what you mean by _really able to be huge_ -- a large single page app? a site with a huge number of pages? # lines of code? I don't think there are any hidden limitations in Angular proper -- in fact it will allow you to organize source for a "large" project very well, and will perform very well -- but you have to be careful with scope digests (i.e. don't try to "compile" a bazillion objects -- but that is mainly common sense)


A lot of articles I originally read/skimmed with Angular didn't really tout it's ability to organize large codebases... I got the impression is targeted toward smaller projects, whereas Backbone they market themselves in your face "we will clean up your large codebase".


Angular and Backbone are very different. Angular is a full framework; it's brilliant but also gets in my way on a regular basis. It may take me longer to write the same app in Backbone but it's a library and happily co-exists with other libraries. With Backbone I feel like I'm using JavaScript, with Angular I'm learning Angular.


I also write a LOT less code, a LOT less boilerplate code -- after writing a number of Angular apps, I won't go back.


I think angular offers some amazing features, but it's very opinionated in how you use it. My experience with angular has left me feeling less like a javascript wrangler and more like an angular wrangler. I mean no disrespect to the framework, because it is amazing, but, it's just different.


Even though the Backbone API has been solid for a very long time, here's hoping the psychological effect of reaching "1.0" continues to spur opinionated abstractions that sit on top of Backbone.


Many thanks to the whole team of contributors for making a very useful and concise library to build upon. Many frameworks take the "batteries included" approach.. and for JavaScript, I feel that can be a bit overkill since each web app has it's own set of requirements. Backbone has proven to provide _just enough_ for structuring web apps and has clearly been useful in a wide variety of projects [1].

[1]: http://backbonejs.org/#examples


I agree completely. I've started using Backbone for the models and validation.

Although I would like to see reactive fields built in; that said I've written an extension to Backbone.Model which gives me that (just ugly syntax)


Have you released the extension anywhere?


No, it was for a work project.


An updated Todo App Example using AMD (RequireJS):

http://ahamlett.com/Backbone.localStorage


For anyone who might be interested, my housemate published a book of Backbone tutorials. You can download it for free from http://backbonetutorials.com/


Both of our apps did not work anymore after the update.

Does

Renamed Collection's "update" to set, for parallelism with the similar model.set(), and contrast with reset. It's now the default updating mechanism after a fetch. If you'd like to continue using "reset", pass {reset: true}.

mean that now collections don't fire the 'reset' event anymore? Should we use collection.on('set', ...) instead? Because I think there are a lot of apps in the wild relying on the collection.on('reset', ...) syntax out there as this is seen in most of the tutorials.


Not quite -- the default has changed. It means you should call:

    collection.fetch({reset: true})
... and everything should continue to work as it did before. That said, this isn't the best forum for debugging help -- you'll probably have faster responses asking on IRC.


ok thanks for clarification. and for backbone in general ;)


This helped me, too. Thanks!


Many congrats and thanks to Jeremy and the other contributors. Backbone's opinion-less approach has been so great for our startup, even if it took me a solid 3 months before I really understood why it was so great. Seriously, coming from working on super-opinionated backend frameworks meant a lot of unlearning when I started using Backbone in October of 2011. Keep up the awesome work!


Congrats Jeremy and team!

I picked up Backbone a couple of years ago (around 0.6). It is balanced at the perfect level of abstraction for me. There have been a ton of frameworks coming up over the last few years but none of them beat Backbone for me.

Thanks for all your work and if there some place I can throw some $USD your way or a charity you prefer, please let us know.


Backbone.js has made me a better JavaScript programmer, thank you Jeremy and everyone else that has contributed to this wonderful project.


I credit backbone with a lot of my success as a front end developer as well. Even though I moved on from the project, the ideas and design decisions have stayed with me.


I just got thrown onto a Backbone w/ Coffee-script project at work. This book has been pretty helpful for getting up to speed: https://www.scriptybooks.com/books/backbone-coffeescript/

and this boilerplate code: https://github.com/quartzmo/backbone-coffeescript-boilerplat...

(which I just added `*.coffee` sourceMapping to!)


Why are the backbone.js controllers called 'views' and the views called 'templates'?


Views are not controllers. Views are more akin to presenters, or viewmodels. You are right that what is traditionally considered a "view" in the rails parlance is a template to backbone.

fwiw, Routers used to be called Controllers.


Looking at the definition of controllers here: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93cont... how are backbone.js 'views' not controllers?

Or does this logic belong in the Route.js file? I am clearly confused.

FYI.. rails didn't invent mvc; it was invented in the 70's for smalltalk.


I think we all know that by now. Backbone doesn't subscribe to neither MVC or MVP. It takes what it needs and does away with the rest. Either you like that or you don't, but that doesn't make it wrong.


I originally came very close to doing just that ... but decided to call the Backbone.View a "View" because it's usually tied very concretely to a specific DOM element. From the perspective of your application, as you're working with the object, it feels like a view.

That said, if it really bugs you, no worries:

    Backbone.Controller = Backbone.View;
Boom.


One of my co-workers comes from a strong server side MVC background; dealing with Backbone has confused him greatly as to the terminology and separation of concerns.

The break-through explanation I gave him is that Backbone views are DOM elements that are code-backed and adhere to OOP principles. They have constructors, properties, methods, etc. Ultimately, though, they are DOM elements. They can derive their content from templates, but they're still just code-backed DOM elements.

They sometimes behave as smart elements.. and sometimes they behave as controllers. Sometimes, depending on necessity, views get rendered and added to the DOM without templates at all (thus the nicety of tagName and attributes). Sometimes views necessitate a template because the result of the view is less dynamic, or merely appends more dynamic views and places them within placeholders in the template.

Point being.. They're not called controllers because they aren't controllers. They can behave as controllers, but... they're still not strictly controllers. The templates aren't called views because, although the UI is a result of the templates, they aren't always the sole source of the UI.

Backbone indeed lacks clear naming conventions if we are to stuff it in to an existing paradigm, but I have no need to do that - and I don't think you should try it either.


Sounds like Django's "MTV" naming of those concepts: http://www.djangobook.com/en/2.0/chapter05.html#the-mtv-or-m...


Yeah, I've started learning Django this week, and one of the first confusing questions I asked myself is "why are there so many templates?". Then I realized a template in Django is like a normal view in Rails or other frameworks.


One thing I really like about Backbone is their excellent documentation. That's the kind of documentation an OpenSource project needs.


> Support for HTTP PATCH requests, sending only the changed state of your model to the server, instead of the full representation.

This feels a little off to me. The nice thing about Backbone vs. other frameworks is that it's not overly opinionated, you can structure your backend any way you want, so I'm not sure why Backbone has an opinion of what http methods save() uses. PUT as a default makes sense but it should be able to support POST, PATCH, GET, CHANGETHETHING or anything else, as browsers now support arbitrary method strings in XHR. Perhaps an override some where?


http://tools.ietf.org/html/rfc5789

HTTP PUT is for in place entire entity updates. HTTP PATCH is for partial updates.

This isn't some opinion these guys came up with. It's HTTP standards.

Also if you don't like what save does. Write your own Backbone.sync and be done with it. Still super flexible.


Fair enough, I agree with the spec here, but we know that in the wild many companies don't conform to HTTP.


For what it's worth... "PATCH is going to be the primary method for updates in Rails 4.0." http://weblog.rubyonrails.org/2012/2/25/edge-rails-patch-is-...

That's not intended to be a counterpoint. In the wild, many companies don't use Rails. :)


It doesn't matter what Rails decides to do if your HTTP server doesn't support it.

With that said, it looks like many do already support it (from the same article you linked): Apache, nginx, Phusion Passenger, Unicorn, Thin, and WEBrick.


Also, Rails supports an override as well, so you can send it as a POST but specify a different verb in a header, and it will treat it as a native request with the correct verb.


Backbone already supports overriding this in several ways:

1. You can pass any arguments to the ajax call in the options hash passed to the various calls:

    Foo = Backbone.Model.extend({url: "/bar" })
    f = new Foo
    f.fetch({type: "BLAH"}) 

    leads to a "BLAH /bar" request instead of a GET.
2. You can override Backbone.sync to do an application-wide override. The basic implementation is fairly simple as a starting point and/or you can just wrap it.

3. You can override the sync methods of Backbone.Model or Backbone.Collection. By default these just proxy to Backbone.sync

4. You can extend either of them and derive your own models and collections from your extended version.

5. You can replace .sync for any _specific_ model or collection object if you have specific sync needs for specific subsets of your application.

Given this, I really don't think cluttering the default code with more options is worthwhile - any other variations would be better provided for by providing an alternate implementation which can optionally proxy to the default/original for cases that doesn't need special handling.

This is part of what I like about Backbone - it is small and focused and sufficiently decoupled that replacing parts of the guts of it is simple to do.


    > PUT as a default makes sense but it should be able to support 
    > POST, PATCH, GET, CHANGETHETHING or anything else, as browsers 
    > now support arbitrary method strings in XHR.
... it does (as mentioned by vidarh). The full suite of jQuery options are passed through transparently. What this particular feature means is that:

    model.save()
    // PUT all of the models current attributes to model.url

    model.save(attrs, {patch: true})
    // PATCH just the `attrs` to model.url


    // Override Backbone.sync to use the PUT HTTP method for PATCH requests
    // when doing Model#save({...}, { patch: true });
    var originalSync = Backbone.sync;
    Backbone.sync = function(method, model, options) {
        if (method === 'patch') options.type = 'PUT';
        return originalSync(method, model, options);
    };


Of all the JS libraries/frameworks I've used Backbone.js is the one I always come back to. Great to see the 1.0 release. Keep up the great work


Here's a great example of the RESTfulness backbone provides: http://duganchen.ca/backbone-js-and-restful-web-services/


Does this mean breaking changes will now go through a deprecation process?


That's a very good question. Depending on the severity of the change, and the popularity of the feature being changed, we'll probably start to explicitly deprecate some things. One (potential) example might be the use of `{silent: true}` to prevent events from being fired.

But that said, the nature of a "breaking change" in Backbone is much less severe than in most open-source libraries. All released versions are published on GitHub, and you can use any version you see fit at any time. In addition, because the codebase is so compact, broken into atomic functions, and thoroughly commented -- it's really easy to patch to suit your own needs, should you find something you need to change without waiting for us to push a new release.

I haven't heard of anyone having a problem yet with a feature that was changed, where one of the above approaches didn't work out.


The suggested options, if I comprehend you properly, are A) Stick with the version you originally programmed against and B) Analyze the overall diff between versions if upgrading.

New features/improvements provide an incentive to not choose Option A. With regard to Option B: Although Backbone may be compact and easy to comprehend, the code calling it is much larger. Analyzing Backbone's changes and factoring in all code that calls it is a difficult and error prone process - laregly due to the dynamic nature of the language and lack of tooling for refactoring.

Two changes that bit us from 0.9.2->0.9.10 were model.set no longer accepting a model and, instead, requiring model.attributes (not a big deal, as it threw an exception and was immediately noticeable). The second issue, with collection.fetch, was a silent failure (I forget the exact issue, but the solution was providing two options, perhaps reset/update/add). Neither of these were documented in the changelogs.

It's not so much an issue of patching these breaking changes as it is knowing about them. Perhaps the ultimate issue here is our lack of adequate testing.


Seems like great timing with the ember conversation on the front page too. Isn't ember a offshoot of backbone?


No. Ember is a fork (conceptually, at least; I'm not sure about common code) of SproutCore: http://yehudakatz.com/2011/12/12/amber-js-formerly-sproutcor...

Ember was Amber for about 2 days but changed due to a naming collision with another project. I really read too much Hacker News.


Congrats to Jeremy and all the contributors. Thanks for all the hard work and diligent attention to details!


It will be awesome if we can couple Backbone with NodeJs to build SEO friendly web apps like Yahoo Mojito.


Great! Will use (eventually)...

Congrats and thanks to Mr Ashkenas.


I always liked Backbone, using it exclusively before switching to ember.js as of recently. I wonder why the authors waited more than 2 years to reach 1.0?


Great , news ! Backbone was the first framework i used to create rich web apps. What's great is that it is both usefull for LOB apps and more specific apps like Games , Complex editors , etc ...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: