ducin
ducin

Reputation: 26437

requirejs fundamentals: underscore + backbone + jquery

I want to make a skeleton app using require.js, backbone.js and underscore.js. I have created a skeleton, according to www tutorials, but I've got a bug somewhere.

This is init.js code:

requirejs.config({
    baseUrl: 'js',
    paths: {
        jquery: 'http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery',
        underscore: 'http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore',
        backbone: 'http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone'
    },
    shim: {
        backbone: {
            deps: ['jquery', 'underscore'],
            exports: 'Backbone'
        },
        underscore: {
            exports: '_'
        },
        jquery: {
            exports: '$'
        }
    }
});

require(['underscore', 'backbone', 'app'],
function(_, Backbone, app) {
    console.log(app);
    app.start();
});

This is app.js:

require(['underscore', 'backbone'],
function(_, Backbone) {

    'use strict';

    return {
        start: function() {
            console.log('APP', 'start');
        }
    };
});

And this is index.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>Wealthy Laughing Duck</title>
        <script data-main="js/init" src="http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.5/require.min.js"></script>
    </head>
    <body>
    </body>
</html>

The problem I'm facing is that app.js file return doesn't work (perhaps something wrong with require.js). The console output is:

undefined ----- init.js:24
Uncaught TypeError: Cannot call method 'start' of undefined ----- init.js:25

The question is: why is app undefined inside init.js, if it's defined in app.js?

Edit: directory structure looks like this:

/ index.html
/ js / init.js
/ js / app.js

Upvotes: 1

Views: 1318

Answers (4)

Tanmay
Tanmay

Reputation: 746

What I observed in your init.js that you are unnecessary loading _ and backbone in your require call. your require call in init.js should be simple like this:

require(['app'],
function(app) {
    console.log(app);
    app.start();
});

This is not the solution to your problem but just a good practice to not to load unwanted scripts.

Basically I think problem here is regarding usage of require and define.

require is always execution and define is definition

Define() function does following three things:

  1. Loads the specified dependencies
  2. Calls the callback function
  3. Registers the return value from the callback function as the module

Require() function only completes steps 1 and 2.

You should use define instead is require in your app.js file as you are defining it there and executing app.js in your init.js file

Upvotes: 0

Lyn Headley
Lyn Headley

Reputation: 11588

Your app.js needs to call define, not require. This will provide a module named 'app' to other modules:

app.js

define(['underscore', 'backbone'],
function(_, Backbone) {

    'use strict';

    return {
        start: function() {
            console.log('APP', 'start');
        }
    };
});

Upvotes: 3

Brendan Delumpa
Brendan Delumpa

Reputation: 1145

I think what you might be experiencing is a bit of syntactical problem more than anything else. Here's how I've set up my require_config.js that I invoke above the require.js:

require.config({
    baseUrl: '/ui/js',
    paths : {
        'incl' : '/ui/incl'
    },
    shim: {
        'backbone': {
            //These script dependencies should be loaded before loading
            //backbone.js
            deps: ['underscore', 'jquery'],
            //Once loaded, use the global 'Backbone' as the
            //module value.
            exports: 'Backbone'
        }
    }
});

This sets up all the dependencies (I don't have a paths member as I just declare backbone and underscore and jquery in script tags). But no matter, once they're all defined, I needn't refer to them again. Here's a simple controller example that demonstrates this point:

require([
    'models/myModel',
    'views/myView
], function(MyModel, MyView) {
    var MyController = function() {
        var my_model = new MyModel();
        var view = new MyView({
            model : my_model
        });
    }

    $(function() {
        new MyController();
    });
});

As you can see, neither jQuery, Backbone nor Underscore are referenced. They've already been loaded.

Upvotes: 0

Rayweb_on
Rayweb_on

Reputation: 3727

I think you need to add app to your paths, in order to require it.

requirejs.config({
    baseUrl: 'js',
    paths: {
        jquery: 'http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery',
        underscore: 'http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4   /underscore',
        backbone: 'http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone'
        app:  '../../App' // your relative pathwhere you have your app.js file
    },
    shim: {
        backbone: {
             deps: ['jquery', 'underscore'],
             exports: 'Backbone'
        },
        underscore: {
            exports: '_'
        },
        jquery: {
            exports: '$'
        }
    }
 });

Upvotes: 0

Related Questions