1
votes

How can I call requireJS require(['app'], function() {}); only once at the beginning for the whole application so that any subsequent require(["..."], function(...){}); don't need to be wrapped within require(['app']?

This is my set up:

1) Load require.js

<script data-main="js/app.js" src="requirejs/require.min.js"></script> 

2) Have app.js shims and basUrl configured properly.

requirejs.config({ 

  baseUrl: "scripts/js",

  paths: { 
    "jquery": "../bower_components/jquery/dist/jquery.min",
    "modernizr": "../bower_components/modernizr/modernizr", 
    .
    . 
    .
  },
  shim: {
    "jquery.migrate": ['jquery'], 
    .
    .
    .
  }
}); 

3) Dynamically load JS on different pages:

// Home Page
require(['app'], function() {

    require(["jquery", "foundation", "foundation.reveal"], function ($, foundation, reveal){
         $(document).foundation(); 
    }); 
});


// Catalog Page
require(['app'], function() {

    require(["jquery", "lnav/LeftNavCtrl","controllers/ProductCtrl", "controllers/TabsCtrl"], function ($, NavCtrl, ProductCtrl, TabsCtrl){
        $(function() {
            NavCtrl.initLeftNav(); 
        });
    }); 
}); 

Unless I wrap with require(['app'], function()) each time I call require("...") to load external JS or AMD modules, the app is not initialized and I get JavaScript errors. The above code works but it's not very efficient.

Is there a way to start my requireJS app before I try loading scripts?

I tried calling at the very beginning right after I load require.min.js:

require(["app"], function (app) {
    app.run();
});

but it didn't work.

1

1 Answers

2
votes

There are no provisions in RequireJS to ensure that a specific module is always loaded before any other module is loaded, other than having your first module load the rest. What you are trying to do is share your first module among multiple pages so it cannot perform the work of loading what is specific to each page.

One way you can work around this is simply to load app.js with a regular script element:

<script src="requirejs/require.min.js"></script>    
<script src="js/app.js"></script>

Then the next script element can start your application without requiring app.js:

<script>
   require(["jquery", "foundation", "foundation.reveal"], function ($, foundation, reveal){
     $(document).foundation(); 
   }); 
</script>

This is actually how I've decided to launch my modules in the applications I'm working on right now. True, it is not as optimized as it could be because of the extra network round-trip, but in the case of the applications I'm working on, they are still in very heavy development, and I prefer to leave this optimization for later.

Note that generally you don't want to use script to load RequireJS modules but your app.js is not a real module as it does not call define, so this is okay.

Another option would be to use a building tool like Grunt, Gulp, Make or something else and create one app.js per page and have each page load its own app.js file. This file would contain the configuration and the first require call to load the modules specific to your page.