Domanda

I've been working on a Backbone app that uses RequireJS for modularization. I feel I've got a good handle on that, but now that we're ready to deploy, I've been battling with r.js all day and am really stuck. I've managed to get the app to build without any errors, but when I try to run the optimized build, it ignores several files that have been built into my output file. Here's the (edited for brevity) build.js file I'm using:

({
    appDir: "main-app",
    baseUrl: "js",
    mainConfigFile: "main-app/js/main.js",
    dir: "build",
    optimize: "none", // for debugging this issue
    findNestedDepencencies: false, // 'true' isn't needed, and didn't fix the issue anyway
    removeCombined: true,
    modules: [
        { name: "main", exclude: ["vendor"] },
        { name: "vendor" }
    ],
    wrap: true
})

The main.js file has been working in non-optimized mode for weeks now. Here's a simplified version of that file:

requirejs.config({
    shim: {
        handlebars: { exports: 'Handlebars' },
        underscore: { exports: '_' },
        backbone: { deps: ['underscore', 'jquery'], exports: 'Backbone' },
        marionette: { deps: ['backbone'], exports: 'Marionette' }
    },
    paths: {
        jquery: "vendor/jquery/jquery",
        handlebars: "vendor/handlebars/handlebars",
        backbone: "vendor/backbone/backbone",
        underscore: "vendor/underscore/underscore",
        marionette: "vendor/marionette/backbone.marionette",
        hbs: "vendor/require-handlebars-plugin/hbs"
    },
    hbs: {
        helperDirectory: "common/templates/helpers/"
    }
});

requirejs(['vendor', 'app', 'controllers'], function(Vendor, Application) {
    Application.start();
});

Where vendor is an empty module that just requires all the 3rd party libraries used, to ensure they're loaded and to make optimization cleaner (I end up with a main.js file with my app code, and a vendor.js file with all the 3rd party code.) The controllers file is the same thing, just with most of the application modules instead.

The problem I'm having is that, after compiling and running the optimized application, require is still trying to load hbs, jquery and underscore from the paths listed in the requirjs.config block, even though I can see that they are being compiled into vendor.js.

if ( typeof define === "function" && define.amd ) {
    define( "jquery", [], function() {
        return jQuery;
    });
}

I spent a good deal of time trying to get hbs compiling, so I'm still trying to determine if that's causing an issue, but I don't know how it would.

È stato utile?

Soluzione 2

I finally got this to work. The core issue had to do with the order of inclusion. In main.js I switched the initialization call to this:

requirejs(['vendor'], function() {
    requirejs(['app'], function(Application) {
        Application.start();
    });
});

Then, in app.js (this is a Marionette application):

Application.on("initialize:after", function() {
    require(['controllers'], function() {
        ... history, setup, etc...
    });
});

Basically, I needed to ensure there were no circular dependencies, which didn't show up during production.

On top of that, I also switched to an AMD-wrapped version of Handlebars, since the shim for that was not working, and switched the exports on the Marionette shim to be Backbone.Marionette, since Marionette wasn't showing up as a global variable.

I found this article to be extremely helpful in getting most of the way there.

Altri suggerimenti

Are you looking for the empy: directive?

In your build config,

({
...
 paths : {
    'jquery' : 'empty:'
 },
})

Assigning the path to empty tells r.js it is externally loaded.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top