Question

I'm working on a web app that uses require.js. I'm quite new to both the app and requirejs and was wondering what the best solution might be for a problem I've run into. We have been loading third-party user analytics / tracking libraries with script tags in PHP include files. We don't use requirejs for these, because php is setting some js runtime values.

Here's an example of one such block:

<script src="//js.revsci.net/gateway/gw.js?csid=A08723"></script>
<script type="text/javascript">
    <?php
        global $base_url;
        $host = parse_url( $base_url, PHP_URL_HOST );
    ?>
    if( typeof DM_cat != 'undefined' ) {
        DM_cat('Track');
        DM_tag();
    }
</script>

Now I agree, it's not ideal to combine js and php like this, but all the analytics code is written this way and there's a lot of it. I don't have time (or knowledge) to refactor it all the requirejs way, so I'm stuck with this structure for the time being. Now I've been asked to make these third-party scripts either 'async' or 'defer'. I'd prefer async if possible, but either would be an acceptable solution. So I want to change this:

<script src="//js.revsci.net/gateway/gw.js?csid=A08723"></script>

to this:

<script src="//js.revsci.net/gateway/gw.js?csid=A08723" defer></script>

My question is, how can I use Require to load the third-party script and prevent the inline javascript block from being executed until the script is loaded? From the code I've tried to write, I keep getting a "Mismatched anonymous define() module" error. I've read up on the error, but I can't make sense of it. Even if I paste in a basic example, I keep getting that error. For example, I can't even get this test code to work:

define(["testcode"], function(testcode){
  window.foo = "bar";
});

define(["foo"], function(){
  alert(window.foo);  // "bar"
});

Error message:

Uncaught Error: Mismatched anonymous define() module: function
(testcode){   window.foo = "bar"; }

I don't understand this error, can anyone help to point me in the right direction? Thanks in advance!

Was it helpful?

Solution

Late to the party, but this error is caused by having 2 define statements in a single file without naming them. This is necessary to distinguish the two modules you are declaring in a single file. You need to add a name parameter like this:

define('Name1', ["testcode"], function(testcode){
  window.foo = "bar";
});

define('Name2', ["foo"], function(){
  alert(window.foo);  // "bar"
});

See these two: - Documentation - Related Stackoverflow Article

OTHER TIPS

nopuck4you suggests that you add the module name as the first argument of the define call. If these modules are created inside of a <script> tag right inside your HTML, then that's okay. This is one of the rare exceptions where you can put a module name as the first argument of define. Actually, in this kind of situation you have to name the modules otherwise RequireJS cannot find them. So you'd have:

<script>
define("foo", ["testcode"], function(testcode){
  window.foo = "bar";
});

define("test", ["foo"], function(){
  alert(window.foo);  // "bar"
});
</script>

(I've assumed that the 2nd module depends on the 1st and named things accordingly. I don't know what the testcode thing is so I left it as is.)

However, in general, you should not give names to modules by putting the name in the define call. The RequireJS documentation is quite clear about this. If you do name your modules in the define, this may cause issues down the road due to the way RequireJS works. Things will not work, or they won't work unless you work around the problem. For instance, if you put modules foo and bar in foo.js and put their names as the first argument of define, RequireJS won't have any trouble figuring that module foo is in foo.js but it won't know right off the bat that bar is also in foo.js. Depending in which order you load your modules, you might have to have additional configuration telling RequireJS that bar is in foo.js.

Putting the names of your modules in the define calls just leads to failures, surprises, complications, etc. Don't do it. Leave the name out and let RequireJS figure it out. Then, when you optimize, let r.js put the names in.

Note: you may have seen some code from 3rd parties that have the module names put right into the define. jQuery is a prominent case. There are exceptions to what I said above but if you cannot articulate a substantial reason why you need to put the name in, then you don't need to do it. (In fact, looking at the jQuery case, I don't see a good reason to put the name in the define there and in my opinion they made a mistake.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top