multipleDefine error in dojoLoader

68120
14
01-07-2015 02:11 PM
ChristopherTotty
New Contributor III

I am working on a js application that uses ArcGIS JS (currently targeting 3.8, referencing through the arcgis cdn).  We have found an issue during internal testing where when the app loads and the dojo require/define chain resolves, periodically the app will fail to load with "multipleDefine" errors being thrown from dojoLoader in esri init.js.  We have a single computer running IE 10 that can easily replicate the error in one or two loads of the page.  Testing on another computer running IE 10 did not provide a replication of the issue.  I have tested on IE 11 as well and was able to replicate a few times over many loads of the app.  This hasn't been enough to go on to track down the cause.

We have a number of custom modules setup with the standard "define" structure.  It appears that when one of these modules loads, a group of the references in the define block fail with the multipleDefine errors.  As an example, there is a custom module that handles the setup and use of a BasemapGallery.  In the case of this module, the errors may occur when loading  'esri/dijit/BasemapGallery', 'esri/dijit/BasemapLayer', 'esri/dijit/Basemap', among others.  These 3 references in particular are only made within this single module in our entire app.

Any thoughts about what could be causing this issue?

Thanks

define([
    'dojo/_base/declare',
    'dijit/_WidgetBase',
    'dijit/_TemplatedMixin',
    'dijit/_WidgetsInTemplateMixin',
    'dojo/_base/lang',
    'dijit/form/DropDownButton',
    'dijit/DropDownMenu',
    'dijit/MenuItem',
    'dojo/_base/array',
    'dojox/lang/functional',
    'dojo/text!./Basemaps/templates/Basemaps.html',
    'esri/dijit/BasemapGallery',
    'esri/dijit/BasemapLayer',
    'esri/dijit/Basemap',
    'dijit/registry',
    'esri/layers/ArcGISTiledMapServiceLayer'
], function (declare, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, lang, DropDownButton, DropDownMenu, MenuItem, array, functional, template, BasemapGallery, BasemapLayer, Basemap, registry, ArcGISTiledMapServiceLayer) {

    //anonymous function to load CSS files required for this module
    (function () {
        var css = [require.toUrl("gis/dijit/Basemaps/css/Basemaps.css")];
        var head = document.getElementsByTagName("head").item(0),
            link;
        for (var i = 0, il = css.length; i < il; i++) {
            link = document.createElement("link");
            link.type = "text/css";
            link.rel = "stylesheet";
            link.href = css[i].toString();
            head.appendChild(link);
        }
    } ());

    var customBasemaps = {
        //SNIP     
    };

    var agolBasemaps = {
        //SNIP   
    };

    // main basemap widget
    return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
        templateString: template,
        widgetsInTemplate: true,
        mode: "agol",
        title: "Basemaps",
        mapStartBasemap: "hybrid",
        basemapsToShow: ["hybrid", "satellite", "streets", "topo", "gray", "oceans", "national-geographic", "osm"],
        validBasemaps: [],
        postCreate: function () {
            //SNIP
        },
        startup: function () {
            this.inherited(arguments);
            if (this.mode === "custom") {
                this.gallery.select(this.mapStartBasemap);
            } else {
                this.map.setBasemap(this.mapStartBasemap);
            }
        }
    });
});
Tags (4)
0 Kudos
14 Replies
HaroldBostic
Occasional Contributor II

Are you using another framework beside dojo, that does dependency injection as well?

0 Kudos
RobertWinterbottom
Occasional Contributor

Try inspecting the error in the console, usually it will give you some clue as to which module is having this issue.  I have seen it before and my solution may not be the same as yours but in our case, we were also loading jquery from a libs folder (this was actually an esri storymap template we were modifying), and in the console I could see the multipleDefine was referencing jquery.  Our fix was in the dojoConfig you can specify aliases as an array, so we configured it to look something like this:

var dojoConfig = {
     packages: [
          { name: 'libs', location: location.pathname.replace(/\/[^/]+$/, "") + '/libs' }
     ],
     aliases: [
          ['jquery', 'libs/jquery']
     ]
}

If you can look at the multipleDefine and figure out which module specifically is giving the issue, that would be a good starting point.

ChristopherTotty
New Contributor III

In addition to esri/dojo, this page also references (via <script>) jquery, jqueryui, and knockout through another cdn.

However, the example custom module described in my previous message does not use those libraries.  I'm not really familiar with how the DI works when the define block references an external module.  I expect that at the time our custom module is loaded, the dojo loader is running through all the referenced modules and making sure they have been loaded.  I assume that is the point when the multipleDefine error is thrown.

What I really don't understand is that the referenced modules that are causing the errors appear to be internal to the esri framework and include modules such as 'esri/dijit/BasemapGallery', 'esri/dijit/BasemapLayer', 'esri/dijit/Basemap'.

0 Kudos
RobertWinterbottom
Occasional Contributor

Almost every time I have seen this it has been due to jquery or some other external library.  They often put shims in the code to make them compatible with AMD and Common JS module formats.  I think it has to do with jquery or other being downloaded before (or after, havent dug into this too much after I figured out how to make it work) the Esri JS API.  Are you referencing jQuery and knockout globally or inside your AMD modules.  If your referencing them in your AMD modules you can try the following:

1. Remove the script tags pulling in JQuery and Knockout

2. Add the CDN to your aliases like so

dojoConfig: {
    ...
    aliases: [
          ['jquery', 'https://code.jquery.com/jquery-2.1.3.min.js '],
          ['knockout', 'http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js ']
    ]
}

3. require them and use them that way

require([
    'jquery',
    'knockout'
], function ($, ko) {
    ...
});
ChristopherTotty
New Contributor III

Thanks, Robert.  I will have to try moving our script referenced to jquery, ko, etc into the dojo package config.  This will take some time since we have other non ADM loaded code that references these libraries from global.

It still seems odd that these would cause an issue when it is the esri modules in the define that are throwing the multipleDefine errors.  After looking at Dennis' post with a similar issue, I would assume the esri module failing would point away from a jquery specific issue since it is not being listed in the returned multipleDefine error, but instead a module from the esri cdn (for example, http://js.arcgis.com/3.8/js/dojo/dijit/DropDownMenu.js‌ )

0 Kudos
DennisHunink
New Contributor III

If you'd look to the source code of jQuery UI you would see there trying to hook into AMD.

Although not tested through and through, it looked a lot like the DoJo loader (also tested with dojo core, without esri) conflicts with jQuery and jQuery UI, when the haven't finished loading.

Seems a lot like it has something to do with this line of code:

if ( typeof define === "function" && define.amd ) {

(from jquery-ui/core.js at master · jquery/jquery-ui · GitHub  )

When jQuery and/or jQuery UI haven't finished loading their modules/scripts but dojo is starting to load, the above if statement seems to prove to be true. Whoever, when you defer loading all dojo stuff until jQuery-ui and jQuery are loaded, the statement will return false (obviously).

I haven't been able to fully test the hypothesis but in practice this works for me:

- load jQuery and jQuery ui in de header, blocking

- load alle my custom code AND the dojo stuff in the footer, deferred

RobertWinterbottom
Occasional Contributor

Ahh ok.  It may be easier to just use what Dennis is suggesting.  Load those scripts in the header and the esri javascript api at the end once those scripts have loaded. 

Not sure why it would point to something like the DropDownMenu.  multipleDefine errors happen generally happen from loading modules via script tags and not the amd loader provided by dojo, or esri in this case, which results in a sort of race condition unless you load them how Dennis is suggesting.  I dont think I have ever had the issue be with a dojo or esri module, its usually a 3rd party library.  However I have noticed the error messages can be misleading, especially looking at the call stack because it may start loading some dojo modules, but then the 3rd party library tries to load, either from the script tag or through a define/require call or both, and it fails and you now have a call stack listing all these dojo modules when the error is really somewhere else.

You can read here about the error, although its only a little snippet about it, just search mulipleDefine on this page: The Dojo Loader — The Dojo Toolkit - Reference Guide . Other than this, there is really not a lot of information floating around that really explains the issue well.

LauraMiles1
Occasional Contributor III

This is an old thread, but just wanted to add that this was the solution for me - moving the jquery-ui reference so that it was loading before the JS API. My multipleDefine error vanished.

KubaSzostak1
New Contributor III

My WebMap application uses jQuery+jQueryMobile and I got the same problem. For me switching to dojo debug mode make my app working.

<script>

  var dojoConfig = { isDebug: true };

</script>

<link rel="stylesheet" href="https://community.esri.com//js.arcgis.com/3.13/esri/css/esri.css">

<script src="http://js.arcgis.com/3.13/"></script>

dojoLoader error still exists but my map is loaded.

See also

Re: Dojo Loader error 

Regards

Kuba