Modulo di definizione () anonimo non corrispondente


129

Ricevo questo errore quando sfoglio la mia webapp per la prima volta (di solito in un browser con cache disabilitata).

Errore: modulo di definizione () anonimo non corrispondente: funzione (richiesto) {

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
    });
});

Qualcuno sa esattamente cosa significa questo errore e perché sta accadendo?

file sorgente , una breve discussione al riguardo nella pagina dei problemi di github

Risposte:


142

Come ha detto AlienWebguy, secondo i documenti, request.js può esplodere se

  • Hai una definizione anonima (" moduli che chiamano define () senza ID stringa ") nel suo tag di script (suppongo che in realtà significhino ovunque nell'ambito globale)
  • Hai moduli con nomi in conflitto
  • Utilizzi plugin di caricamento o moduli anonimi ma non usi l'ottimizzatore di request.js per raggrupparli

Ho avuto questo problema includendo bundle creati con browserify insieme ai moduli request.js. La soluzione era:

A. caricare i bundle standalone non require.js nei tag script prima del caricamento di request.js, oppure

B. caricali utilizzando require.js (anziché un tag di script)


2
i nomi in conflitto sono comuni
Julio Marins

1
Un'altra possibile soluzione, in alcuni casi speciali con moduli anonimi, è quella di sovrascrivere la funzione requestjs.onError al fine di prevenire l'eccezione di errore predefinita generata da requestjs che interrompe l'esecuzione di moduli o codice successivi.
xtrm,

1
Ho appena aggiunto una richiesta pull ( github.com/requirejs/requirejs/pull/1763 ) per rilassare il caso esatto. Penso che sia un problema molto comune in questi giorni.
Bob S

1
Grazie per avermi detto di caricarli prima! Non so perché questo suggerimento non sia nella documentazione richiesta da Requjs ... Ecco dove lo stack è utile
Tobias Feil

14

Ho avuto questo errore perché ho incluso il file requestjs insieme ad altre librerie incluse direttamente in un tag di script. Quelle librairie (come lodash) utilizzavano una funzione di definizione che era in conflitto con la definizione di Require. Il file requestjs si stava caricando in modo asincrono, quindi ho il sospetto che la definizione del requisito sia stata definita dopo la definizione delle altre librerie, quindi il conflitto.

Per sbarazzarsi dell'errore, includere tutti gli altri file js utilizzando requirejs.


Si è scoperto che molte librerie fanno una cosa del genere, o almeno usano / esportano una tale funzione. Consiglio a tutti - se lo usano richiedono - importa tutto con un requisito :)
Andrey Popov

12

Iniziando con un reattore mi sono imbattuto nel problema e come principiante i documenti potrebbero anche essere stati scritti in greco.

Il problema che ho riscontrato è stato che la maggior parte degli esempi per principianti usa "definizioni anonime" quando dovresti usare un "ID stringa".

definisce anonimo

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


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

definire con id stringa

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

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

Quando si utilizza define con un ID stringa, si eviterà questo errore quando si tenta di utilizzare i moduli in questo modo:

require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
    moduleOne.helloWorld();
    moduleTwo.helloWorld2();
});

(Solo una nota per i posteri) Ci sono alcuni aspetti negativi di questo approccio, descritti nei documenti : "Definire () le chiamate che includono un nome per il modulo ... sono normalmente generate dallo strumento di ottimizzazione ... nam [ing] moduli voi stessi ... rende il moduli meno portatili ... Normalmente è meglio evitare la codifica in un nome per il modulo e lasciare che lo strumento di ottimizzazione bruci nei nomi dei moduli. " ... così come in questo thread GitHub . Questo sembra essere il motivo per cui è elencato il nome negli esempi per principianti.
Mark G.

10

Secondo i documenti :

Se si codifica manualmente un tag di script in HTML per caricare uno script con una chiamata define () anonima, questo errore può verificarsi.

Visto anche se si codifica manualmente un tag di script in HTML per caricare uno script che ha alcuni moduli con nome, ma quindi si prova a caricare un modulo anonimo che finisce con lo stesso nome di uno dei moduli con nome nello script caricato manualmente tag script codificato.

Infine, se si utilizzano i plug-in di caricamento o i moduli anonimi (moduli che chiamano define () senza ID stringa) ma non si utilizza l'ottimizzatore RequireJS per combinare i file insieme, questo errore può verificarsi. L'ottimizzatore sa come nominare correttamente i moduli anonimi in modo che possano essere combinati con altri moduli in un file ottimizzato.

Per evitare l'errore:

  • Assicurati di caricare tutti gli script che chiamano define () tramite l'API RequireJS. Non codificare manualmente i tag di script in HTML per caricare script che contengono chiamate define () al loro interno.

  • Se si codifica manualmente un tag di script HTML, assicurarsi che includa solo i moduli con nome e che non sia caricato un modulo anonimo che avrà lo stesso nome di uno dei moduli in quel file.

  • Se il problema è l'uso di plugin caricatore o moduli anonimi ma l'ottimizzatore RequireJS non viene utilizzato per il raggruppamento di file, utilizzare l'ottimizzatore RequireJS.



5

Tieni presente che alcune estensioni del browser possono aggiungere codice alle pagine. Nel mio caso avevo un plug-in "Emmet in all textareas" che incasinava le mie richieste. Assicurati che nessun codice aggiuntivo sia aggiunto al tuo documento controllandolo nel browser.


5

Le risposte esistenti spiegano bene il problema, ma se includere i file di script utilizzando o prima di requestJS non è un'opzione facile a causa del codice legacy, una soluzione leggermente confusa è rimuovere il requisito dall'ambito della finestra prima del tag dello script e quindi ripristinarlo dopo le parole. Nel nostro progetto questo è racchiuso in una chiamata di funzione sul lato server, ma in effetti il ​​browser vede quanto segue:

    <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>

Non è il più pulito ma sembra funzionare e ha risparmiato molti rifrattori.


5
In realtà non farlo mai. Non funziona correttamente in IE.
jcbdrn,

2
A intermittenza in IE gli script inclusi in requestJS avrebbero definito mancanti dal loro ambito finestra anche quando il comando request veniva dopo che le variabili erano state ripristinate. Non siamo mai riusciti a capire perché ciò è accaduto, quindi abbiamo abbandonato questa soluzione caotica.
jcbdrn,

2
@jcbdrn Non è solo su IE. L'ho visto accadere su un'altra piattaforma. Il motivo è che le specifiche HTML offrono garanzie riguardo all'ordine di esecuzione degli script sincroni ma solo rispetto ad altri script sincroni . Non garantisce l'esecuzione di script asincroni rispetto a uno sincrono (o viceversa). Quindi nel codice mostrato nella risposta qui, è possibile avere uno script asincrono eseguito tra due scriptelementi qualsiasi .
Louis,

Se hai la possibilità di modificare il bundle js che stai importando, puoi semplicemente avvolgere il tutto in questo modo:(function(){ var define = undefined; // the UMD registration code won't find the global 'define' anymore! // generated content goes here })()
Pete Thorne,

2

Oppure puoi usare questo approccio.

  • Aggiungi require.js nella tua base di codice
  • quindi carica lo script tramite quel codice

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

Cosa farà caricherà il tuo script dopo aver caricato require.js .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.