0

I'm compiling some of my dojo stuff for the first time today. Just for simplicity while fighting this beast, I compiled everything I had (except dojo.js) into this one file called all.js.

But in all.js, I have an entry point that's totally sealed in this anonymous function that I need to call, but it's not very obvious to me how to get at it.

Here's the start of the file:

require({cache:{
'dojo/dom-geometry':function(){
 define(["./sniff", "./_base/window","./dom", "./dom-style"],
    function(has, win, dom, style){
// module:
//      dojo/dom-geometry

// the result object
var geom = {
    // summary:
    //      This module defines the core dojo DOM geometry API.
};
//dom-geometry continues on for awhile....

and the part I'm interested in, on line 14798! How can I call CreateActivityEntryPoint?

   //end of previous part
    return singleton;
});

},
'app/Activity/Create':function(){


function CreateActivityEntryPoint()
{
    //do things here.
}

Here's the part that comes after:

}, //closing bracket of Activity/Create anon function
'dojo/dom-attr':function(){
define(["exports", "./sniff", "./_base/lang", "./dom", "./dom-style", "./dom-prop"],
        function(exports, has, lang, dom, style, prop){
    // module:

In my main page view, I just need to call the entry point. Previously it was simply on the window object, but not anymore! How do I call the Create.js file functions out of this "cache:" object?

I've tried:

require(["app/Activity/Create"], function (create) {
          create.CreateActivityEntryPoint();
      });

but create is undefined, it seems.

Isaac Bolinger
  • 7,328
  • 11
  • 52
  • 90
  • It appears that I need properly define my code modules so that they can call each other. I guess tomorrows job is figuring that out. – Isaac Bolinger Feb 05 '15 at 06:43
  • I think you need to `define` the modules not `require`. you need to replace your `require({cache:{.....` to `define({cache:{.....`. **require** is for requiring modules whereas **define** is for defining a module. **define** returns a module with a set of properties and methods, which can be called for interactions with the module. – frank Feb 05 '15 at 08:36
  • can you show us the source code for `app/Activity/Create` **before** the build process. It should contain a `define` call. – frank Feb 05 '15 at 08:42
  • I think you are right. I am really glad i tried to compile this before my javascript got too huge. – Isaac Bolinger Feb 05 '15 at 12:50
  • @frank, direct modification of a built layer module should never be necessary. `require({cache: ... })` calls are a mechanism by which a layer can directly populate the AMD loader's cache, the point being so that a number of modules can be populated at once so that referencing their module IDs via `require` or `define` later will load them from the loader's cache rather than actually generating server requests and trying to load each file individually. – Ken Franqueiro Feb 05 '15 at 13:44

1 Answers1

2

Generally you access functions the same way after compiling a custom layer as before - by obtaining a reference to the module via require or define and passing the module's identifier. (This is how code inside the layer also continues to work.) The only difference is that with a built layer, you want to only be doing this after the layer has loaded (otherwise the loader will end up making requests for individual modules that you don't actually want it to make because it should be loading them all together via the layer).

If your layer corresponds to a top-level entry point exposing the function you need to call, or you build your layer directly into dojo/dojo so that all of your modules are available as soon as dojo.js loads (explained a bit more below), you don't need to do anything special - just require([ 'app/myEntryPoint' ], function (entryPoint) { ... }) and call the function you need to call within the require callback.

Otherwise, if your layer does not correspond to a top-level entry point exposing the function you need to call, and you compile a separate layer rather than directly building into dojo/dojo, you will need to go a bit out of your way to ensure your layer is loaded before you try interacting with other code, in order to avoid superfluous requests for individual modules that are actually in the layer:

require([ 'app/layer' ], function () {
    require([ 'app/moduleWithEntryPoint' ], function (moduleWithEntryPoint) {
        moduleWithEntryPoint.entryPoint(...);
    });
});

The rest of this response talks a bit about ideal build profile configuration.

Typically the recommended way to organize layers for ease of maintenance and use is to create one layer around a top-level entry point module for your application; ideally this entry point would transitively include all of the dependencies of the application. For example, app/main could be your entry point; it might depend on app/UI which is your top-level application widget, which would depend on further widgets, stores, etc. and the dependency chain would continue downward.

Defining a layer around a top-level module is insanely simple, since the build automatically includes the module referenced by a layer's module ID, and automatically includes all transitive dependencies:

layers: {
    'app/main': {}
}

To reduce requests even more, though, you can build this layer directly into dojo.js:

layers: {
    'dojo/dojo': {
        boot: true, // This layer includes the Dojo loader
        customBase: true, // Override the default of including all of dojo/_base
        include: [ 'app/main' ]
    }
}

In either of these cases, when you do require([ 'app/main' ], function (app) { ... }), it will end up pulling all of the individual dependencies from the require cache, while still handing you the return value of the main module, so you can access any functions you use to initialize your application.

Ken Franqueiro
  • 10,559
  • 2
  • 23
  • 40
  • Is this freenode dojo channel a better place to go to get help? – Isaac Bolinger Feb 06 '15 at 02:04
  • Well, I've cut my requests down alot! I ended up compiling into the single dojo file. HOWEVER: there's a bunch of xhr requests still coming through. For instance, it xhr requests dojo/sniff. But dojo sniff is definitely in the new compiled dojo file. Wonder what's wrong... – Isaac Bolinger Feb 06 '15 at 02:44
  • Whether here or on IRC, we'd probably need to see more code to help with that (namely, what the page that is trying to load the layer but ends up still loading extra modules looks like). IRC is generally active during daytime in US timezones, though there are a couple of people from the New Zealand area or thereabouts sometimes too. – Ken Franqueiro Feb 06 '15 at 13:14
  • I'll see how far I can get on my own, I haven't investigated a lot of the build options yet. Thanks for your help Ken, I appreciate it! – Isaac Bolinger Feb 06 '15 at 19:32
  • Setting data-dojo-config="async:1" got my dojo related requests down to 2: one for the css file and one for dojo.js. This is great! – Isaac Bolinger Feb 06 '15 at 19:41
  • Oh, in that case you were probably building `dojo/dojo` with `customBase: true`, but by default (without `async: true`) the loader loads all the legacy `dojo/_base` stuff - some of which probably wasn't in your layer (and you probably don't really want to load). – Ken Franqueiro Feb 07 '15 at 01:51