Nicht übereinstimmendes anonymes define () -Modul

129

Ich erhalte diese Fehlermeldung, wenn ich meine Webanwendung zum ersten Mal durchsuche (normalerweise in einem Browser mit deaktiviertem Cache).

Fehler: Nicht übereinstimmendes anonymes define () -Modul: function (require) {

HTML :

<html>
   .
   .
   .
   <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
   <script> var require = { urlArgs: "v=0.4.1.32" }; </script>
   <script data-main="assets/js/main" src="assets/js/libs/require.js"></script>
   <script src="assets/js/ace/ace.js?v=0.4.1.32"></script>
   </body>
</html>

JS :

$(function () {
    define(function (require) {
        // do something
    });
});

Weiß jemand genau, was dieser Fehler bedeutet und warum er auftritt?

Quelldatei , eine kurze Diskussion darüber auf der Seite mit den Github-Problemen

Adonis K. Kakoulidis
quelle

Antworten:

142

Wie AlienWebguy sagte, kann require.js laut den Dokumenten explodieren, wenn

  • Sie haben eine anonyme Definition (" Module, die define () ohne Zeichenfolgen-ID aufrufen ") in einem eigenen Skript-Tag (ich nehme an, sie bedeuten tatsächlich irgendwo im globalen Bereich).
  • Sie haben Module mit widersprüchlichen Namen
  • Sie verwenden Loader-Plugins oder anonyme Module, verwenden jedoch nicht den Optimierer von require.js, um sie zu bündeln

Ich hatte dieses Problem, als ich mit browserify erstellte Bundles neben require.js-Modulen einfügte. Die Lösung war entweder:

A. Laden Sie die eigenständigen Bundles non-require.js in Skript-Tags, bevor require.js geladen wird, oder

B. Laden Sie sie mit require.js (anstelle eines Skript-Tags).

BT
quelle
2
widersprüchliche Namen sind weit verbreitet
Julio Marins
1
Eine andere mögliche Lösung, in einigen speziellen Fällen mit anonymen Modulen, besteht darin, die Funktion requirejs.onError zu überschreiben, um zu verhindern, dass die von requirejs ausgelöste Standardfehlerausnahme die Ausführung aufeinanderfolgender Module oder Codes stoppt.
XTRM
1
Ich habe gerade eine Pull-Anfrage hinzugefügt ( github.com/requirejs/requirejs/pull/1763 ), um genau diesen Fall zu lockern. Ich denke, es ist heutzutage ein sehr häufiges Problem.
Bob S
1
Danke, dass du mir gesagt hast, ich soll sie vorher laden! Ich weiß nicht, warum dieser Tipp nicht in der eigenen Dokumentation von requirejs enthalten ist ... Hier bietet sich der Stapel an
Tobias Feil
14

Ich hatte diesen Fehler, weil ich die Datei requirejs zusammen mit anderen Bibliotheken, die direkt in einem Skript-Tag enthalten sind, eingefügt habe. Diese Bibliotheken (wie lodash) verwendeten eine Definitionsfunktion, die im Widerspruch zur Definition von require stand. Die requirejs-Datei wurde asynchron geladen, daher vermute ich, dass die Definition der Anforderung definiert wurde, nachdem die anderen Bibliotheken definiert wurden, daher der Konflikt.

Um den Fehler zu beseitigen, fügen Sie alle anderen js-Dateien mit requirejs ein.

eloone
quelle
Es stellte sich heraus, dass viele Bibliotheken so etwas tun oder zumindest eine solche Funktion verwenden / exportieren. Ich werde jedem raten - wenn sie erfordern verwenden - alles mit erfordern importieren :)
Andrey Popov
12

Als ich mit den Reaktionen anfing, stieß ich auf das Problem, und als Anfänger können die Dokumente auch auf Griechisch geschrieben sein.

Das Problem, auf das ich gestoßen bin, war, dass die meisten Anfängerbeispiele "anonyme Definitionen" verwenden, wenn Sie eine "Zeichenfolgen-ID" verwenden sollten.

anonym definiert

define(function() {
        return { helloWorld: function() { console.log('hello world!') } };
 })


define(function() {
        return { helloWorld2: function() { console.log('hello world again!') } };
 })

Definieren Sie mit der Zeichenfolgen-ID

define('moduleOne',function() {
    return { helloWorld: function() { console.log('hello world!') } };
})

 define('moduleTwo', function() {
      return { helloWorld2: function() { console.log('hello world again!') } };
})

Wenn Sie define mit einer Zeichenfolgen-ID verwenden , vermeiden Sie diesen Fehler, wenn Sie versuchen, die Module wie folgt zu verwenden:

require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
    moduleOne.helloWorld();
    moduleTwo.helloWorld2();
});
P.Brian.Mackey
quelle
(Nur ein Hinweis für die Nachwelt) Es gibt einige Nachteile bei diesem Ansatz, beschrieben in der Dokumentation : „definieren () Anrufe , die einen Namen für das Modul enthalten ... werden in der Regel durch die Optimierungs - Tool ... nam erzeugt [ing] Module selbst ... macht die Module weniger portabel… Normalerweise ist es am besten, die Codierung eines Namens für das Modul zu vermeiden und das Optimierungstool einfach in den Modulnamen brennen zu lassen. “ … Sowie in diesem GitHub-Thread . Dies scheint der Grund zu sein, warum die Auflistung des Namens in den Anfängerbeispielen ausgeschlossen ist.
Mark G.
10

Gemäß den Dokumenten :

Wenn Sie ein Skript-Tag manuell in HTML codieren, um ein Skript mit einem anonymen define () -Aufruf zu laden, kann dieser Fehler auftreten.

Dies wird auch angezeigt, wenn Sie ein Skript-Tag manuell in HTML codieren, um ein Skript mit einigen benannten Modulen zu laden. Versuchen Sie dann jedoch, ein anonymes Modul zu laden, das denselben Namen wie eines der benannten Module im manuell geladenen Skript hat codiertes Skript-Tag.

Wenn Sie die Loader-Plugins oder anonymen Module (Module, die define () ohne Zeichenfolgen-ID aufrufen) verwenden, aber den RequireJS-Optimierer nicht zum Kombinieren von Dateien verwenden, kann dieser Fehler auftreten. Der Optimierer weiß, wie anonyme Module korrekt benannt werden, damit sie mit anderen Modulen in einer optimierten Datei kombiniert werden können.

So vermeiden Sie den Fehler:

  • Stellen Sie sicher, dass Sie alle Skripte, die define () aufrufen, über die RequireJS-API laden. Codieren Sie Skript-Tags nicht manuell in HTML, um Skripte zu laden, in denen define () -Aufrufe enthalten sind.

  • Wenn Sie ein HTML-Skript-Tag manuell codieren, stellen Sie sicher, dass es nur benannte Module enthält und dass ein anonymes Modul, das denselben Namen wie eines der Module in dieser Datei hat, nicht geladen wird.

  • Wenn das Problem in der Verwendung von Loader-Plugins oder anonymen Modulen besteht, der RequireJS-Optimierer jedoch nicht für die Dateibündelung verwendet wird, verwenden Sie den RequireJS-Optimierer.

AlienWebguy
quelle
3
Ist das ein anonym definiertes Modul? github.com/requirejs/example-multipage/blob/master/www/js/app/…
Straßenlaterne
5

Beachten Sie, dass einige Browsererweiterungen den Seiten Code hinzufügen können. In meinem Fall hatte ich ein Plugin "Emmet in all textareas", das meine Anforderungen durcheinander brachte. Stellen Sie sicher, dass Ihrem Dokument kein zusätzlicher Code hinzugefügt wird, indem Sie ihn im Browser überprüfen.

Vektor
quelle
5

Die vorhandenen Antworten erklären das Problem gut, aber wenn das Einfügen Ihrer Skriptdateien mit oder vor requireJS aufgrund von Legacy-Code keine einfache Option ist, besteht eine leicht hackige Problemumgehung darin, require vor Ihrem Skript-Tag aus dem Fensterbereich zu entfernen und es anschließend nach den Worten wieder herzustellen. In unserem Projekt ist dies hinter einem serverseitigen Funktionsaufruf eingeschlossen, aber der Browser sieht effektiv Folgendes:

    <script>
        window.__define = window.define;
        window.__require = window.require;
        window.define = undefined;
        window.require = undefined;
    </script>
    <script src="your-script-file.js"></script>        
    <script>
        window.define = window.__define;
        window.require = window.__require;
        window.__define = undefined;
        window.__require = undefined;
    </script>

Nicht das ordentlichste, scheint aber zu funktionieren und hat viel Refractoring gespart.

jcbdrn
quelle
5
Mach das eigentlich nie. Im IE funktioniert es nicht richtig.
jcbdrn
2
In IE haben die in requireJS enthaltenen Skripte zeitweise definiert, dass sie in ihrem Fensterbereich fehlen, selbst wenn der Befehl require nach der Wiederherstellung dieser Variablen kam. Wir haben nie herausgefunden, warum dies passiert ist, also haben wir diese hackige Lösung aufgegeben.
jcbdrn
2
@jcbdrn Es ist nicht nur auf IE. Ich habe es auf einer anderen Plattform gesehen. Der Grund dafür ist, dass die HTML-Spezifikation Garantien hinsichtlich der Reihenfolge der Ausführung synchroner Skripte bietet, jedoch nur relativ zu anderen synchronen Skripten . Es garantiert nicht die Ausführung von asynchronen Skripten relativ zu synchronen (oder umgekehrt). In dem in der Antwort hier gezeigten Code ist es also möglich, ein asynchrones Skript zwischen zwei beliebigen scriptElementen ausführen zu lassen .
Louis
Wenn Sie die Möglichkeit haben, das zu importierende Bundle js zu bearbeiten, können Sie das Ganze einfach so einpacken:(function(){ var define = undefined; // the UMD registration code won't find the global 'define' anymore! // generated content goes here })()
Pete Thorne
2

Oder Sie können diesen Ansatz verwenden.

  • Fügen Sie require.js in Ihre Codebasis ein
  • Laden Sie dann Ihr Skript über diesen Code

<script data-main="js/app.js" src="js/require.js"></script>

Was es tun wird, wird Ihr Skript nach dem Laden von require.js geladen .

Umar Asghar
quelle