0

In my application, I want to have an environment config that uses a different version name for every deploy so that the application is properly cache busted and users don't have stale versions of code in their browser cache. Note I have been following this guide.

Thus, in main.js, before I do anything, I call require.config with a generic config that uses the current date/time to bust the cache on the environment config file, then after the environment config is loaded, I use the environment "config.version" as part of the urlArgs to guarantee that the newly deployed code is included and not a stale version. Note that the object from the config file has other properties that will be used throughout the application as well (e.g. google analytics account number).

It seems that my r.js build file is fine if I remove the first require.config that allows me to setup the environment/config dependency, but when I add it back in, the infrastructure JS module that I'm using to group third-party scripts chokes saying it can't find my underscore lib (or any lib I include in there for that matter). Note that even if I don't include environment/config and just make the two require.config calls, the same error results. Is there a reason two require.config calls would cause this error? Thanks for any help.

//Error:
Error: ENOENT, no such file or directory '<%root_folder%>\dist\js\underscore.js'
    In module tree:
        infrastructure

My main JS file

//main.js
require.config({
  baseUrl: "js",
  waitSeconds: 0,
  urlArgs: "bustCache=" + (new Date).getTime()
});
require(["environment/config"], function(config) {
  "use strict";
  require.config({
    urlArgs: "bustCache=" + config.version,
    baseUrl: "js",
    waitSeconds: 0,
    paths: {
      underscore: "lib/lodash.underscore-2.4.1-min",
    },
    shim: {
      "underscore":{
        exports : "_"
      }
    }
  });
  //commented out, b/c not needed to produce the error
  //require(["jquery", "infrastructure"], function($) {
    //$(function() {
      //require(["app/main"], function(app) {
        //app.initialize();
      //})
    //});
  //});
});

And here's the build file...

//build file
({
    mainConfigFile : "js/main.js",
    appDir: "./",
    baseUrl: "js",
    removeCombined: true,
    findNestedDependencies: true,
    dir: "dist",
    optimizeCss: "standard",
    modules: [
        {
            name: "main",
            exclude: [
                "infrastructure"
            ]
        },
        {
            name: "infrastructure"
        }
    ],
    paths: {
        "cdn-jquery": "empty:",
        "jquery":"empty:",
        "bootstrap.min": "empty:"
    }
})

Here infrastructure.js

 define(["underscore"], function(){});

config file (will have more keys like google analytics account number and other environment specific info.)

//config.js
define({version:"VERSION-XXXX", cdn: { jquery: "//path-to-jquery-1.11.0.min" }});

command I'm running: "r.js -o build.js"

Daniel
  • 1,603
  • 15
  • 13
  • @Louis, I added the config file as requested. Is there anything else that is unclear? – Daniel Oct 15 '14 at 02:30
  • I copied out the error to the question text, included infrastructure.js, and removed all superfluous references in the code to get the minimum case to observe the problem. Basically, anything included in "infrastructure.js" is not recognized, so it throws an error. If I remove the reliance on the environment/config file to setup the code, then infrastructure JS doesn't complain about not being able to find libraries. – Daniel Oct 15 '14 at 13:58
  • Note that even if I don't include environment/config and just make the two require.config calls, the same error results, meaning I actually tried: require.config({//first config object}); followed by require.config({//second config object}); within the same scope level, and the error resulted. – Daniel Oct 15 '14 at 14:20

1 Answers1

1

Ok, yes, it is a problem with the two require.config calls. At runtime, there is absolutely no problem calling config multiple times. However, at build time, r.js is not able to follow the calls. So if your build depends on any later call to require.config you are going to have problems.

I see that your second call to require.config does not contain any value that is computed on the basis of what is loaded after the first call, except for urlArgs so you could move everything from that second call into the first one, except for urlArgs.

Louis
  • 128,628
  • 25
  • 249
  • 295
  • Yeah, I did end up restructuring the calls, but this means that my CDN includes will have to be inline rather than from a config file unless I have some other build magic to replace them. I guess as I get further into the process of writing the deployment script, I might find some solution for this external to r.js, but for now I don't see a way to get around this limitation. Thanks for the help! – Daniel Oct 15 '14 at 17:09
  • In large applications, I find myself using scripts to generate configurations or modify them during a build. It seems unavoidable as applications become more complex. – Louis Oct 15 '14 at 17:12