Search code examples
requirejsjs-amdwijmo

RequireJS Path With JS Extension Not Resolving


I am using a library that (very selfishly, IMHO) assumes that the baseUrl will point to the company's CDN:

baseUrl: "[http protocol slash slash]cdn.wijmo.com/amd-js/"

At first I thought that I would just copy the contents of the above Url to my own folder (such as /scripts/wijmo/amd-js), but that doesn't work because the good folks at Wijmo hardcoded path references in their AMD define statements, such as this:

define(["./wijmo.widget"], function () { ... });

What the above means (if I understand things properly) is that if you have any other non-Wijmo AMD modules then you must either:

(a) place them under the amd-js path, perhaps in a sub-folder named "myScripts" (b) use hard-coded RequireJS path references to your own AMDs, like this:

paths: {
  "myAMD_1": "http://www.example.com/scripts/myScripts/myAMD_1",
  "myAMD_2": "/scripts/myScripts/myAMD_2.js"
}

(a) works, but it means that the baseUrl cannot point to the Wijmo CDN because I don't have access to the Wijmo CDN site so I must move the files published under amd-js to my own server.

(b) sort of work, and here is my problem: If I use syntax myAMD_1 then all is well. But that doesn't let me test on my local development machine, which uses localhost. (I don't want to get into detecting which server I'm running on and customize the paths value... I want the path to remain the same before and after I publish to my http server.)

Now, according to the RequireJS documentation:

There may be times when you do want to reference a script directly and not conform to the "baseUrl + paths" rules for finding it. If a module ID has one of the following characteristics, the ID will not be passed through the "baseUrl + paths" configuration, and just be treated like a regular URL that is relative to the document: * Ends in ".js". * Starts with a "/". * Contains an URL protocol, like "http:" or "https:".

When I try to end (terminate) my path reference with .js (as shown in AMD_2 above), RequireJS doesn't find my AMD and because it ends up looking for myAMD_2.js.js (notice the two .js suffixes). So it looks like RequireJS is no longer honoring what the docs say it employs as a path-resolution algorithm. With the .js suffix not working properly, I can't easily fix references to my own AMDs because I don't know for sure what server name or physical path structure they'll be published to--I really want to use relative paths.

Finally, I don't want to change Wijmo's AMD modules not only because they're are dozens of them, but also because I would need to re-apply my customizations each time they issue a Wijmo update.

So if my baseUrl has to point to a hard-coded Wijmo path then how can I use my own AMDs without placing them in a subfolder under the Wijmo path and without making any fixed-path or Url assumptions about where my own AMDs are published?


Solution

  • I can suggest a couple of approaches to consider here--both have some drawbacks, but can work.

    The first approach is to provide a path for each and every Wijmo module that needs to be loaded. This will work, but you have touched on the obvious drawbacks of this approach in the description of the question: Wijmo has many modules that will need to be referenced, and maintaining the module list across updates in the future may be problematic.

    If you can live with those drawbacks, here is what the RequireJS config would look like:

    require.config({
        paths: {
            'wijmo.wijgrid': 'http://cdn.wijmo.com/amd-js/wijmo.wijgrid',
            'wijmo.widget': 'http://cdn.wijmo.com/amd-js/wijmo.widget',
            'wijmo.wijutil': 'http://cdn.wijmo.com/amd-js/wijmo.wijutil',
            // ... List all relevant Wijmo modules here
        }
    });
    
    require(['wijmo.wijgrid'], function() { /* ... */ });
    

    The second approach is to initially configure the RequireJS baseUrl to load the Wijmo modules. Then once Wijmo modules have been loaded, re-configure RequireJS to be able to load your local app modules. The drawback of this approach is that all the Wijmo modules will need to be loaded up front, so you lose the ability to require Wijmo modules as needed within your own modules. This drawback will need to be balanced against the nastiness of listing out explicit paths for all the Wijmo modules as done in the first approach.

    For example:

    require.config({
        baseUrl: 'http://cdn.wijmo.com/amd-js',
        paths: {
            // ... List minimal modules such as Jquery and Globalize as per Wijmo documentation
        }
    });
    
    require(['wijmo.wijgrid'], function() { 
        require.config({
            baseUrl: '.'
        });
    
        require(['main'], function() {
            /* ... */
        });
    });