3
votes

I am using Backbone / Marrionette and AMD Require.js

My goal is to speed up the web application load time by concatenating all of the files. Less files I have to load, the greater the load speed.

So fat I have achieved to concatenate files within the /lib folder. Those files are jQuery, underscore, backbone... simply normal lib folder. After I do concatenation, I receive file called main.js that has all of the files in it. And that works, however I am failing to concatenate my application files. I am using r.js to do the task

Here is the application folder structure:

  • css
  • img
  • js

    • views (most of the files are here)
    • collections
    • models
    • regions
    • routers
    • lib
    • controllers

    app.js config.js main.js

This is the build file that I use against the above structure:

appDir: './',
baseUrl: './js',
dir: './dist',
modules: [
    {
        name: 'main'
    }
],
fileExclusionRegExp: /^(r|build)\.js$/,
optimizeCss: 'standard',
removeCombined: true,
paths: {
    underscore        : 'lib/underscore',
    backbone        : 'lib/backbone',
    babysitter  : 'lib/backbone.babysitter',
    wreqr       : 'lib/backbone.wreqr',
    marionette        : 'lib/backbone.marionette',
    handlebars  : 'lib/handlebars',
    jquery                : 'lib/jquery',
    jqueryui        : 'lib/jqueryui',
    text        : 'lib/text',
    templates   : '../templates'
},
shim: {
    underscore: {
        exports: '_'
    },
    backbone: {
        exports: 'Backbone',
        deps: ['jquery', 'underscore']
    },
    jqueryui: {
        exports: '$',
        deps: ['jquery']
    },
    babysitter: {
        exports: 'Backbone.Babysitter',
        deps: ['backbone']
    },
    wreqr: {
        exports: 'Backbone.Wreqr',
        deps: ['backbone']
    },
    marionette: {
        exports: 'Backbone.Marionette',
        deps: [
            'backbone',
            'babysitter',
            'wreqr',
            'lib/json2'
        ]
    },
    handlebars: {
        exports: 'Handlebars'
    },

    'lib/marionette.handlebars': {
        exports: 'Marionette.Handlebars',
        deps: ['handlebars', 'marionette']
    },
    'lib/foundation': {
        exports: '$',
        deps: ['jquery']
    },
    'lib/foundation.orbit': {
        exports: '$',
        deps: ['lib/foundation']
    },
    'lib/foundation.reveal': {
        exports: '$',
        deps: ['lib/foundation']
    },
    'lib/foundation.dropdown': {
        exports: '$',
        deps: ['lib/foundation']
    }
},
deps: ['jquery', 'underscore']

This is app.js file:

define([
'marionette',
'lib/marionette.handlebars',
'wreqr',
'routers/router',
'views/header_view',
'views/footer_view',
'lib/foundation',
'lib/foundation.dropdown',
'lib/foundation.orbit',
'lib/foundation.reveal',
'controllers/format_controller'
], function(
Marionette, 
MarionetteHandlebars, 
Wreqr, 
Router, 
HeaderView, 
FooterView,
Foundation,
Dropdown,
Orbit,
Reveal,
FormatController
)
{
var App = new Marionette.Application();

App.addRegions({
    header  : '#header',
    main    : '#main',
    footer  : '#footer'
});

App.addInitializer(function(config) {          
    $.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
        options.xhrFields = {
            withCredentials: true
        };
    });
    // Make the application config available via request/response.
    this.reqres.setHandler('config', _.bind(function() {
        return config;
    }, this));
    // Make the application session available via request/response.
    this.reqres.setHandler('session', _.bind(function() {
        return null;
    }, this));
});
App.addInitializer(function(config) {
    App.request = new Wreqr.RequestResponse();          
    new Router({vent: App.vent, reqres: App.reqres});
    Backbone.history.start();
});
// Initialize any utilities that will be available through vent or reqres.
App.addInitializer(function(config) {
    // String formatter for dates, etc.
    new FormatController({vent: App.vent, reqres: App.reqres});
})

App.vent.on('app:main:show', function(view, isLoggedIn) {
    App.header.close();
    App.main.close();
    App.footer.close();

    var totalRegionsShown = (isLoggedIn) ? 3 : 1;

    var initFoundation = _.after(totalRegionsShown, function() {
        $(document).foundation();
    });

    if (isLoggedIn) {
        var headerView = new HeaderView({
                reqres: view.reqres
        });
        headerView.on('show', _.bind(initFoundation, this));
        App.header.show(headerView);

        var footerView = new FooterView();
        footerView.on('show', _.bind(initFoundation, this));
        App.footer.show(footerView);
    }

    view.on('show', _.bind(initFoundation, this));
    App.main.show(view);
});
return App;

And finally this is my main.js file:

require.config({
baseURL: '.',
urlArgs: "ver=2", //Control Client Cache. Change this value for every new release.
paths: {
    underscore    : 'lib/underscore',
    backbone      : 'lib/backbone',
    babysitter    : 'lib/backbone.babysitter',
    wreqr         : 'lib/backbone.wreqr',
    marionette    : 'lib/backbone.marionette',
    handlebars    : 'lib/handlebars',
    jquery        : 'lib/jquery',
    jqueryui      : 'lib/jqueryui',
    text          : 'lib/text',
    templates     : '../templates'
},
waitSeconds: 60,
shim: {
    underscore: {
        exports: '_'
    },
    backbone: {
        exports: 'Backbone',
        deps: ['jquery', 'underscore']
    },
    jqueryui: {
        exports: '$',
        deps: ['jquery']
    },
    babysitter: {
        exports: 'Backbone.Babysitter',
        deps: ['backbone']
    },
    wreqr: {
        exports: 'Backbone.Wreqr',
        deps: ['backbone']
    },
    marionette: {
        exports: 'Backbone.Marionette',
        deps: [
            'backbone',
            'babysitter',
            'wreqr',
            'lib/json2'
        ]
    },
    handlebars: {
        exports: 'Handlebars'
    },
    'lib/marionette.handlebars': {
        exports: 'Marionette.Handlebars',
        deps: ['handlebars', 'marionette']
    },
    'lib/foundation': {
        exports: '$',
        deps: ['jquery']
    },
    'lib/foundation.orbit': {
        exports: '$',
        deps: ['lib/foundation']
    },
    'lib/foundation.reveal': {
        exports: '$',
        deps: ['lib/foundation']
    },
    'lib/foundation.dropdown': {
        exports: '$',
        deps: ['lib/foundation']
    }
 },
deps: ['jquery', 'underscore']
});

require(['app', 'backbone', 'config'], function(App, Backbone, Config) {

var runEnvironment = "stg";
console.log(Config[runEnvironment]);

console.log("Running environment is: "  + runEnvironment);
App.start(Config[runEnvironment]);
});

Is it possible to do what I need to do given the application structure, or do I need to reorganize the application upside down?

Let me repeat again, that the given build.js gives me whole lib folder concatenated. So I have considerably speed up and reduction of close to 15 java files. However, views, models, controller, routes... are not touched at all.

1
Is the missing }); after return App; at the end of the app.js file a copy/paste typo?g10

1 Answers

1
votes

Have a look at https://github.com/archfirst/keel.

We are using Keel framework for all our Backbone applications. Check the gruntfile. This is following the similar folder structure, and handles the optimization.