3

With the scope of having the javascript side of an existing app, better structured, easy to manage/understand and better management of scripts that need to run for different parts of the site, I decided to try and implement RequireJS as a solution.

I also use grunt, and I took advantage of the grunt-contrib-requirejs existing module, to manage it all in one place.

Grunt

requirejs: {
    options: {
        baseUrl: "./",
        mainConfigFile: "<%= project.scripts %>/build.js",
        name: "<%= project.bowerDir %>/almond/almond",
        out: "<%= project.scripts %>/main.min.js"
    },

    debug: {
        options: {
            optimize: 'none'
        }
    },

    production: {
        options: {
            optimize: 'uglify2'
        }
    }
},

build.js

requirejs.config({
    baseUrl: "/",

    // automatically require on page load in debug mode
    deps: ['assets/scripts/main'],
    //deps: ['main'],

    // automatically require this for production build
    // insertRequire: ['assets/scripts/main'],

    paths: {
        "bower" : "../../../bower_components",
        "module": "../modules",

        "jquery"               : "bower_components/jquery/dist/jquery",
        "jquery.ui"            : "assets/scripts/vendor/jquery-ui-1.10.3.custom.min",
        "jquery.ui.touch-punch": "assets/scripts/vendor/jquery.ui.touch-punch.min",
        "lazyload"             : "bower_components/jquery.lazyload/jquery.lazyload",

        "swfobject"            : "assets/scripts/vendor/swfobject",
        "cookie"               : "assets/scripts/vendor/jquery.cookie",
        "query"                : "assets/scripts/vendor/jquery.query",
    }
}).call(this);

// Load the main app module to start the app
// requirejs(["app", "module/home"]);

main.js

define([
    'jquery', 'jquery.ui', 'jquery.ui.touch-punch',
    'lazyload', 'swfobject', 'cookie', 'query'
    ], function (require) {

    'use strict';

    $(function () {
        alert('main.');
        // ....
    });

});

So, I got to the point where I invoke my build.js (development env... read this article: Grunt.js and Require.js - compiling with r.js)...

<script data-main="/assets/scripts/build" src="/assets/scripts/vendor/require.js"></script>

So, the build.js is loaded, and then the main.js also, and the alert executes. So far, so good... now comes the doubts:

  • I can't seem to understand how to work with dependencies (from jquery to cookie and query). How can I expect them to be already loaded? Because, on my main.js I will invoke those libraries, but I get errors due to the fact that they're not loaded.
  • Let's say for /articles I have articles.js, for /profiles I have profiles.js. How will I manage to process each .js according to the pages I need/want to? main.js is the common file, but there are separate .js files for each module in the web.
  • Am I missing something?
2
  • Since you are just getting started with RequireJS I would pause and take a look at Browserify (browserify.org). It takes the guess work out of everything (paths, shims, etc), by allowing you to simply write require statements like you would in NodeJS. $ = require('jquery') would be how you assign jQuery to the dollar sign so long as it's loaded via NPM in your node_modules. Want to use libs already written? module.exports what you're returning. It makes web components awesome. I haven't used RequireJS since I've found it. Commented Jun 10, 2014 at 19:41
  • @iamjpg thanks for the suggestion. I'll have a look into it Commented Jun 10, 2014 at 19:44

2 Answers 2

3

Within requirejs, you can specify dependancies for each shim. (http://requirejs.org/docs/api.html#config-shim)

So if file a.js depends on file b.js to exist prior to loading, you can specify a dependency on file a. Each time you require file a, it will first require file b.

Example:

requirejs.config({
baseUrl: "/",

// automatically require on page load in debug mode
deps: ['assets/scripts/main'],
//deps: ['main'],

// automatically require this for production build
// insertRequire: ['assets/scripts/main'],

paths: {
    "a"               : "assets/scripts/vendor/a",
    "b"                : "assets/scripts/vendor/b",
},
shim: {
    "a": {
        deps: ["b"]
    }
}

}).call(this);
Sign up to request clarification or add additional context in comments.

Comments

0

You need to provide valid identifiers as arguments in the define callback (your entry point). Demo with a shortened list:

define([
    'jquery',
    'jquery.ui',
    'cookie'

], function(
    $,
    jQueryUI,
    MyCookie

) {

    'use strict';

    alert( $ ); //your local jQuery
    jQueryUI.doSomething();
    MyCookie.fooBar( 'I was required' );

});

Identifier names are of your choice, but I'd suggest to stick to some conventions. There is more than that in require.js, but this could get you started.

2 Comments

I want other libraries (like the cookie one), to be loaded automatically, without having me invoking one by one, because there are a couple of them
"I want" is not a valid argument in JS programming. You can try to register them as globals on the first load, but it really depends on those libs themselves.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.