_CORE
AI & Agentic Systems Core Information Systems Cloud & Platform Engineering Data Platform & Integration Security & Compliance QA, Testing & Observability IoT, Automation & Robotics Mobile & Digital Banking & Finance Insurance Public Administration Defense & Security Healthcare Energy & Utilities Telco & Media Manufacturing Logistics & E-commerce Retail & Loyalty
References Technologies Blog Know-how Tools
About Collaboration Careers
CS EN
Let's talk

Backbone.js — finally structured JavaScript

08. 11. 2011 6 min read CORE SYSTEMSdevelopment

Our JavaScript files keep growing. What started as a few lines of jQuery for form validation and AJAX calls has turned into thousands of lines of incomprehensible code. jQuery is great for DOM manipulation, but it provides no structure for organizing application logic. Backbone.js by Jeremy Ashkenas solves exactly this problem — it brings models, collections, views and a router to frontend development.

Why we need structure on the frontend

Three years ago, a typical web frontend was simple — the server rendered HTML, jQuery added a few interactive effects. But as user expectations grew, the frontend became more complex. Gmail, Google Maps, Facebook — these applications run predominantly in the browser, and the server serves mainly as an API. When you have thousands of lines of JavaScript without a clear structure, every change becomes a risk.

The problem isn’t jQuery — jQuery does exactly what it was designed to do. The problem is the absence of architectural patterns on the frontend. On the server we have MVC (Spring MVC, Rails, Django), dependency injection, a service layer. On the frontend we had a file full of $() selectors and anonymous functions. Backbone.js is the first widely adopted attempt to change this state of affairs.

Models

A Backbone Model represents a data entity — a user, a product, an order. A model contains attributes (data), validation logic and methods for communicating with the server (save, fetch, destroy). The key feature is that a model fires events when attributes change — when a user’s name changes, all views displaying that name update automatically.

This is the fundamental principle of data binding — the Model is the single source of truth and views react to it. In the jQuery world, we typically stored data in the DOM (in attributes, in element text) and JavaScript read from and wrote to it there. With Backbone, models are separated from the presentation. Want to change a user’s name? Change the model attribute and all views update themselves.

Models also abstract communication with the server. Backbone assumes a RESTful JSON API. Calling model.save() sends a POST or PUT request to the server, model.fetch() loads data via GET, model.destroy() sends DELETE. The URL is automatically derived from the root URL of the collection and the model ID. This convention over configuration approach significantly reduces boilerplate code.

Collections

A Collection is an ordered set of models of the same type. A collection of users, a collection of products, a collection of orders. Collections provide methods for adding, removing, filtering and sorting models. Thanks to integration with Underscore.js (Backbone’s sibling), you have a rich set of functional methods at your disposal — map, filter, reduce, find, sortBy, groupBy.

Just like models, collections fire events — add, remove, reset, sort. A view displaying a product list can listen to these events and automatically re-render when data changes. Add a new product? The collection fires an add event, the view adds a new row to the list. Delete a product? The remove event, the view removes the row. No manual DOM manipulation.

Views

A Backbone View is responsible for rendering HTML and handling user interactions. Each view is associated with a DOM element and can listen to DOM events (click, submit, keyup) within its element. A view typically listens to model changes and re-renders when they occur.

Backbone does not prescribe a templating system — you can use anything from simple string templates through Underscore templates to Handlebars or Mustache. We use Handlebars because it offers logic helpers and partials without allowing complex logic in templates (separation of concerns). The view prepares data from the model, passes it to the template, and inserts the resulting HTML into the DOM.

An important detail — Backbone views do not automatically ensure efficient re-rendering. When you call render(), the entire view content is replaced with new HTML. For simple views this is not a problem, but for complex lists with dozens of items it can be slow. Optimization requires more granular updates — instead of re-rendering the entire list, update only the changed row. This is an area where Backbone leaves the decision to the developer.

Router

The Backbone Router maps URL hash fragments to functions. When a user navigates to #users/123, the router calls a function that loads the user with ID 123 and displays the appropriate view. This enables creating a single-page application with full browser history and bookmark support. The user can use back and forward buttons, share URLs and refresh the page without losing state.

The router is simpler than routers in server-side frameworks — no middleware, no named routes, no nesting. For more complex applications this can be a limitation and we often see developers creating their own abstraction on top of the Backbone router. But for the basic use case, the built-in router is sufficient.

Our Backbone architecture

After several projects, we have developed a standard architecture for Backbone applications. At the top is an Application object that initializes the router and shared services. The router delegates to Controller objects (Backbone doesn’t have these natively — we added them), which coordinate data loading and view creation. Views are hierarchical — the main layout view contains regions and each region hosts a specific sub-view.

For communication between unrelated views, we use an event aggregator — a global event bus on which views can fire and listen to events. This prevents direct dependencies between views and makes the code more flexible. For example, the cart view doesn’t call the product catalogue view directly — instead it fires a product:add-to-cart event and the cart listens.

This architecture is inspired by the Marionette.js framework by Derrick Bailey, which adds concepts like regions, layouts and composite views to Backbone. We are considering its full adoption for our next project.

Testing

Backbone code is well testable because models and collections do not depend on the DOM. You can test model validation, computed attributes and API interaction using unit tests without a browser. For testing we use Jasmine — a BDD framework for JavaScript with clean syntax (describe, it, expect). For views we test that they correctly render HTML and respond to events.

We mock API calls using Sinon.js FakeServer, which intercepts AJAX requests and returns pre-prepared responses. This allows testing the entire flow — from data loading through the model to display in the view — without a real server.

Backbone’s limitations

Backbone is intentionally minimalist. Jeremy Ashkenas designed it as a “minimal set of tools for structuring JavaScript”, not as a complete framework. That means you have to solve a lot of things yourself — memory management (unsubscribing event listeners when destroying views), efficient list rendering, communication between views, lazy loading of modules. For each of these problems there are community solutions, but they are not part of the core framework.

It’s also important to note that Backbone is not the only option. Knockout.js offers declarative data binding. Ember.js is a more complete framework with conventions. And on the horizon looms AngularJS from Google, which promises a radically different approach. But today, in autumn 2011, Backbone is the most mature and most widely adopted choice for structuring frontend JavaScript.

Conclusion

Backbone.js brings much-needed structure to frontend development. Models, Collections, Views and Router are the fundamental building blocks that enable organizing a growing JavaScript codebase. It’s not a silver bullet — it requires discipline and supplementary libraries — but it is a huge step forward over jQuery spaghetti. We recommend it to every team building a non-trivial web application.

backbone.jsjavascriptmvc
Share:

CORE SYSTEMS

Stavíme core systémy a AI agenty, které drží provoz. 15 let zkušeností s enterprise IT.

Need help with implementation?

Our experts can help with design, implementation, and operations. From architecture to production.

Contact us