RequireJS load only concatenated file

I'm using RequireJS (version 2.1.14) and would like to concatenate my JavaScript files into one single app-built.js. I've created a little node module which reads my app.js, extracts the project paths and gets executed once I run node build in the js directory of my application.

The node module (build.js):

var fs = require('fs'),
    path = require('path'),
    directory = __dirname + path.sep,
    requirejs = require(directory + 'vendor/r.js');

fs.readFile(directory + 'app.js', 'utf8', function(err, data) {
    if (err) {
        console.log('Error: ' + err);
        return
    } else {
        data = data.replace(/'/g, '"').replace(/\s+/g, '');
        var paths = data.substr(data.indexOf('{'), data.indexOf('}')),
            paths = paths.substr(0, paths.indexOf('}') + 1),
            paths = JSON.parse(paths);

        createAppBuilt(paths);
    }
});

function createAppBuilt(paths) {
    var config = {
        baseUrl: __dirname,
        paths: paths,
        name: 'app',
        out: 'app-built.js',
        preserveLicenseComments: false,
        findNestedDependencies: true,
        removeCombined: true
    };

    requirejs.optimize(config, function(buildResponse) {
        var contents = fs.readFileSync(config.out, 'utf8');
        console.log('Created app-built.js');
    }, function(err) {
        console.log('Error: ' + err);
        return;
    });
}

app.js:

var paths = {
    'jquery': 'vendor/jquery-1.11.0.min',
    // other paths
};

// Set language, necessary for validtaion plugin -> validation.js
if (Modernizr.localstorage) {
    localStorage.getItem('language') || localStorage.setItem('language', navigator.language || navigator.userLanguage);
}

requirejs.config({
    paths: paths,
    shim: {
        touchswipe: {
            deps: ['jquery']
        },
        icheck: {
            deps: ['jquery']
        },
        validate: {
            deps: ['jquery']
        },
        mask: {
            deps: ['jquery']
        },
        chosenImage: {
            deps: ['jquery', 'chosen']
        },
        cookie: {
            deps: ['jquery']
        }
    }
});

require(['globals', 'jquery', 'underscore'], function() {

    var initial = ['main'];

    if (!Modernizr.localstorage) {
        initial.push('cookie');
    }

    require(initial, function(Main) {
        $(function() {
            if (!Modernizr.localstorage) {
                $.cookie.json = true;
            }
            Main.init();
        });
    });

});

The app-built.js gets generated but when I include it in my index.php all the other modules get loaded as well. How can I prevent the loading of all modules and only load the app-built.js?

enter image description here

I recommend you look into http://webpack.github.io/ or http://browserify.org/ as these solve this problem for you.

They allow you to use require much as before, yet the code is compiled/concatenated into a single file.

Webpack allows for a bit more flexibility in loading different chunks of code for different parts of your site, but Browserify is the most well-known so far.

There may be a cost in switching over to these, as I don't think that they're 100% compatible requirejs, however they bring great advantages.

Here's someone's journey from RequireJS to Browserify with some Pros and Cons.

Separate modules into different files, e.g. app-built.js, user-built.js. Then load script when it's needed.

Here's a demo: http://plnkr.co/edit/s6hUOEHjRbDhtGxaagdR?p=preview .

When page loaded, requirejs only loads global.js. After clicking the Change Color button, requirejs starts to load colorfy.js and random-color.js, which required by colorfy.js.

I am not sure about the exact details, but, yet if you don't have an exports option, r.js doesn't define a named module for you, that causes to actually load the script.

I assume you have jquery plugins there so add this extra exports option:

shim: {
    touchswipe: {
        deps: ['jquery'],
        exports: 'jQuery.fn.touchswipe'
    },

This should force r.js to build a named module for touchswipe:

define("touchswipe", (function (global) {
    return function () {
        var ret, fn;
        return ret || global.jQuery.fn.touchswipe;
    };
}(this)));

Note that, exports option might not build this named module, in that case your best bet is to include this manually.

Again I am not sure about why and how this happens, It must be a bug in requirejs, it's unlikely there is a tweak for this.

Changing the r.js optimizer (to uglify2) solved the problem for me:

var config = {
    baseUrl: __dirname,
    paths: paths,
    name: 'app',
    out: 'app-built.js',
    findNestedDependencies: true,
    preserveLicenseComments: false,
    removeCombined: true,
    optimize: 'uglify2'
};