Avoiding RequireJS circular dependencies My app module bootstraps a Backbone.js application.
I need app to be available in every other view for easy access to router, triggering navigation, etc.

I never ported an app to RequireJS before, and I got stuck on circular dependency problem, and this answer isn't quite clear to me, so I'm not sure if I applied the solution correctly.

I'm using AMD sugar style throughout the app, so here's what I came up with:

app.js

define(function (require, exports) {

  'use strict';

  var _ = require('underscore'),
      Backbone = require('backbone'),
      Router = require('Router'),
      AppView = require('common/views/app_view'),

  // ...

  return _.extend(exports, {
    start: function () {
      this.router = new Router();
      Backbone.history.start();

      this.appView = new AppView();
      this.appView.render();
    },

    // ...
  });

});


Extending exports instead of directly returning an object allows me to do app = require('app') in any view of the app without worrying about circular dependencies.

All other modules in the app return value normally (i.e. I'm not using exports anywhere else).

Is this an OK strategy for a Require.js Backbone app?
Are there better solutions (that will also work with optimizer or Almond)?

An example of how I'm using app in a (rather deeply nested) view:

zine_item_view.js

define(function (require) {

  'use strict';

  var View = require('common/views/view'),
      Misc = require('common/helpers/misc'),
      app = require('app');

  var ZineItemView = View.extend({
    template: 'templates/social/items/zine_item.html',

    events: {
      'click': 'showZine'
    },

    showZine: function (e) {
      if (!Misc.shouldHandleClick(e)) {
        return;
      }

      app.presenter.showZine({
        zine: this.model,
        route: app.router.routeToZineTrending(this.model.id)
      });
    }
  });

  return ZineItemView;

});
There are few ways to solve your problem with Backbone.js + Require.js and executing functions or changing routes from view.

1. Using Backbone.Router

Here is approach I've used multiple times:

'use strict';

// Your view --------------
define([
    'jquery'
    'backbone'
    'common/views/view',
    'common/helpers/misc'
], function ($, Backbone, View, Misc) {

    var ZineItemView = View.extend({
        ...
        showZine: function (e) {
          if (!Misc.shouldHandleClick(e)) {
            return;
          }
          // Pass all control from view to the router,
          // see http://stackoverflow.com/a/20311253/1363799
          Backbone.history.navigate('yourUrl_to_zine');
        }
    });

    return ZineItemView;
});

// Main block --------------
require([
    'jquery'
    'backbone',
    'app',
    'ZineItemView'
], function($, Backbone, App, ZineItemView) {
    ...

    var app = new App();

    var zineItemView = new ZineItemView({...});

    // Router way       
    var router = Backbone.Router.extend({
      routes: {
        "yourUrl_to_zine": "showZine"
      },
      showZine: function() {
            // Here you gave access to zineItemView.model and zineItemView.model.id
            app.presenter.showZine({
                zine: zineItemView.model,
                // I think next row becames obsolete
                route: app.router.routeToZineTrending(zineItemView.model.id)
            });
        }
    });
});


2. Event-driven approach

'use strict';

// Your view --------------
define([
    'jquery',
    'backbone',
    'common/views/view',
    'common/helpers/misc'
], function ($, Backbone, View, Misc) {

    var ZineItemView = View.extend({
        ...
        showZine: function (e) {
          if (!Misc.shouldHandleClick(e)) {
            return;
          }

          var view = this;

          // Trigger global event with desired parameters
          $(window).trigger('showZine.App', {
            zine: view.model,
            modelId: view.model.id // probably it's obsolete, because you can get it from zine property
          });
        }
    });

    return ZineItemView;
});

// Somewhere in app block --------------
// lodash is a dependency, because we use bind method
var App = {
    initialize: function() {
        $(window).on('showZine.App', _.bind(this.presenter.showZine, this) );
    },
    presenter: {
        showZine: function(event, paramsObj) {
            // Here you have paramsObj,
            // with paramsObj.zine = zineItemView.model
            // and paramsObj.modelId = zineItemView.model.id

            // Call app.router.routeToZineTrending from here, but be aware about value of `this` and `app` variables
        }
    }
};


3. Syntax of module defining (optional)

It preferentual, but seems to be a standart (it's easier to see dependencies):


'use strict';

define([
    'common/views/view',
    'common/helpers/misc',
    'app'
], function (View, Misc, app) {

    var ZineItemView = View.extend({
        ...
    });

    return ZineItemView;
});