Modular Backbone.js with RequireJS

Written by Backbone Tutorials Team

Last updated: June 2026 · 8 min read

A Backbone app that starts as one script file is comfortable right up to the day it is not. Models, Views, a Router, and a pile of jQuery callbacks pack into a single global scope, and soon you cannot tell which file owns what. Splitting the app into modules with RequireJS fixes that, and it is the setup behind one of the most cited phrases in the Backbone world, require.js plus backbone.js equals robust apps.

This example walks through a small but complete modular Backbone app: the folder layout, the RequireJS config, how a Model and a View are defined as AMD modules, and how the whole thing boots from a single entry point. Code shown runs on Backbone.js 1.6.0 with RequireJS 2.3.

data-mainmain.js RequireJS router.js views/user.js models/user.js App runs

What you'll learn

  • Why split a Backbone app into modules
  • Setting up RequireJS
  • Defining a Model and a View module
  • Bootstrapping the app
  • How RequireJS resolves dependencies
  • Taking it further with a build step

Why split a Backbone app into modules

Backbone gives you objects but says nothing about how to load them. Drop everything in one file and every Model, View, and helper shares the global scope, load order becomes fragile, and two developers editing the same file collide constantly. Modules solve all three problems at once by giving each piece its own file with explicit dependencies.

RequireJS implements the AMD format, which means a file declares what it needs and returns what it provides. Nothing leaks onto window, and the loader works out the order for you.

Setting up RequireJS

Two things get a RequireJS project running: a predictable folder layout and a single configuration file that the page points to.

The folder layout

A small app reads clearly when modules are grouped by type. Models, Views, Collections, and templates each get a folder, with one entry file at the root.

js/
  lib/        backbone.js, underscore.js, jquery.js, require.js
  models/     user.js
  views/      user.js
  router.js
  main.js     <- entry point

The main config file

The page loads RequireJS with a data-main attribute pointing at main.js. That file declares where the libraries live and, for non AMD scripts like older Backbone builds, how they depend on each other through a shim.

require.config({
  baseUrl: "js",
  paths: {
    jquery: "lib/jquery", underscore: "lib/underscore", backbone: "lib/backbone"
  },
  shim: {
    backbone: { deps: ["underscore", "jquery"], exports: "Backbone" },
    underscore: { exports: "_" }
  }
});
require(["router"], function (Router) { new Router(); });

Defining a Model and a View module

Each module wraps its code in define, lists its dependencies, and returns a single value. Here the View depends on the Model.

A Model module

// models/user.js
define(["backbone"], function (Backbone) {
  return Backbone.Model.extend({
    defaults: { name: "" }
  });
});

A View module that depends on it

// views/user.js
define(["backbone", "models/user"], function (Backbone, User) {
  return Backbone.View.extend({
    render: function () {
      this.$el.text(this.model.get("name"));
      return this;
    }
  });
});

Bootstrapping the app

The Router is the natural entry point. It pulls in the Views it needs, and RequireJS guarantees each dependency is ready before the Router method runs.

The app entry point

// router.js
define(["backbone", "views/user", "models/user"],
function (Backbone, UserView, User) {
  return Backbone.Router.extend({
    routes: { "": "home" },
    home: function () {
      var view = new UserView({ model: new User({ name: "Ada" }) });
      $("#app").html(view.render().el);
    }
  });
});

How RequireJS resolves dependencies

You never list files in load order yourself. Each module names what it needs, and the loader walks that graph, fetching and running files in the right sequence.

Letting the loader build the graph

When the Router asks for views/user, RequireJS sees that the View asks for models/user and backbone, fetches those first, then hands the finished objects back. Circular references are the one thing to avoid, since two files that each need the other cannot both be ready first.

Taking it further with a build step

Loading a dozen small files is fine in development but means a dozen requests in production. The RequireJS optimizer, r.js, follows the same dependency graph and concatenates everything into one minified file, so the app you ship is a single download while your source stays neatly split. That combination, clean modules in development and one bundle in production, is the practical payoff of going modular.

Frequently Asked Questions

Why use RequireJS with Backbone?

Backbone does not load files for you. RequireJS gives each Model, View, and Collection its own module with explicit dependencies, keeps the global scope clean, and resolves load order automatically.

What does the shim config do?

Older Backbone and Underscore builds are not written as AMD modules. The shim tells RequireJS what each one depends on and what global it exports, so they load correctly alongside true modules.

How do I avoid loading many files in production?

Run the RequireJS optimizer, r.js. It follows your dependency graph and concatenates everything into a single minified file, so development stays modular while production ships one bundle.

Does this still work with modern Backbone?

Yes. The example runs on Backbone.js 1.6.0 with RequireJS 2.3. Many teams now use ES modules or a bundler instead, but the AMD pattern shown here remains a clear way to structure a Backbone app.

Ready to structure a real Backbone app?

Read the complete guide to organizing Backbone with modules.

Organizing Backbone using modules →