Search code examples
requirejsrequirejs-optimizer

RequireJS baseUrl and multiple optimized files


I've separated out my 3rd party libraries from my app code and grouped them all together into a vendor.js file for requirejs to pull in. In my build.js file, I'm using the modules syntax to optimize my main application, excluding the vendor scripts, and to optimize the vendor.js file. The only issue I'm having is when my compiled main module requests vendor, it's getting the baseUrl from the config file and so doesn't load the optimized vendor.js file. My build.js file looks like this:

({
    baseUrl: "js",
    dir: "build",
    mainConfigFile: "js/main.js",
    removeCombined: true,
    findNestedDependencies: true,
    skipDirOptimize: true,
    inlineText: true,
    useStrict: true,
    wrap: true,
    keepBuildDir: false,
    optimize: "uglify2",
    modules: [
        {
            name: "vendor"
        },
        {
            name: "main",
            exclude: ["vendor"]
        }
    ]
})

And my main.js file looks like this:

requirejs.config({
    baseUrl: "js",
    paths: {
        jquery: 'vendor/jquery/jquery-2.1.3.min',
        bootstrap: 'vendor/bootstrap/bootstrap.min',
        handlebars: 'vendor/handlebars/handlebars-v2.0.0',
        backbone: 'vendor/backbone/backbone-min',
        underscore: 'vendor/lodash/lodash.underscore',
        marionette: 'vendor/marionette/backbone.marionette.min',
        models: 'common/models',
        collections: 'common/collections'
    }
});

define(['module', 'vendor'], function(module) {
    var configPath = "config/config." + module.config().env;
    require([configPath, 'app', 'jquery'], function(config, Application, $) {
        $(function() {
            // Kick off the app
            Application.start(config);
        });
    });
});

All development is done in the js folder, and my build.js file is outside that folder. The optimized files end up in build, a sibling to js, but when I include my main file like this:

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

It ends up loading js/vendor.js for that define() call. What am I missing here? How can I tell the optimized main file to load build/vendor.js instead, yet allow the unoptimized version to still load js/vendor.js?


Solution

  • Ok, I figured this out. It was simple, really, just a case of too much configuration. When you load your script using data-main, the baseUrl is set relative to that file. So, if I specified js/main, the baseUrl would be js. But, since I explicitly specified baseUrl in the config block of main.js, that gets overridden, both in development and production. By removing baseUrl: "js" from main.js, everything works as expected. The development build loads everything relative to js and the production build loads everything (vendor.js) relative to build when I change data-main to build/main. Hope this helps somebody else someday.

    requirejs.config({
        paths: {
            jquery: 'vendor/jquery/jquery-2.1.3.min',
            ...
        }
    });
    
    // 'vendor' is loaded relative to whatever directory main.js is in
    define(['module', 'vendor'], function(module) {
        ...
    });