Module define () anonyme incompatible

129

J'obtiens cette erreur lorsque je navigue sur mon application Web pour la première fois (généralement dans un navigateur avec un cache désactivé).

Erreur: module define () anonyme incompatible: 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
    });
});

Quelqu'un sait exactement ce que signifie cette erreur et pourquoi cela se produit?

fichier source , une brève discussion à ce sujet dans la page des problèmes de github

Adonis K. Kakoulidis
la source

Réponses:

142

Comme AlienWebguy l'a dit, selon la documentation, require.js peut exploser si

  • Vous avez un define anonyme (" modules qui appellent define () sans ID de chaîne ") dans sa propre balise de script (je suppose en fait qu'ils signifient n'importe où dans la portée globale)
  • Vous avez des modules qui ont des noms en conflit
  • Vous utilisez des plugins de chargement ou des modules anonymes mais n'utilisez pas l'optimiseur de require.js pour les regrouper

J'ai eu ce problème en incluant des bundles construits avec browserify aux côtés des modules require.js. La solution était de:

A. chargez les bundles autonomes non-require.js dans les balises de script avant de charger require.js, ou

B. les charger en utilisant require.js (au lieu d'une balise script)

BT
la source
2
les noms contradictoires sont courants
Julio Marins
1
Une autre solution possible, dans certains cas particuliers avec des modules anonymes, est d'écraser la fonction requirejs.onError afin d'empêcher l'exception d'erreur par défaut lancée par requirejs qui arrête l'exécution des modules ou du code successifs.
xtrm
1
Je viens d'ajouter une pull request ( github.com/requirejs/requirejs/pull/1763 ) pour assouplir ce cas précis. Je pense que c'est un problème très courant ces jours-ci.
Bob S
1
Merci de m'avoir dit de les charger avant! Je ne sais pas pourquoi cette astuce n'est pas dans la documentation de requirejs ... C'est là que la pile est utile
Tobias Feil
14

J'ai eu cette erreur parce que j'ai inclus le fichier requirejs avec d'autres librairies inclus directement dans une balise de script. Ces librairies (comme lodash) utilisaient une fonction de définition qui était en conflit avec celle de require. Le fichier requirejs se chargeait de manière asynchrone, donc je soupçonne que la définition du require a été définie après la définition des autres bibliothèques, d'où le conflit.

Pour vous débarrasser de l'erreur, incluez tous vos autres fichiers js à l'aide de requirejs.

éloone
la source
Il s'est avéré que beaucoup de bibliothèques font une telle chose, ou du moins utilisent / exportent une telle fonction. Je conseillerai à tout le monde - s'ils utilisent require - tout importer avec require :)
Andrey Popov
12

En débutant avec reactjs, j'ai rencontré le problème et en tant que débutant, la documentation peut aussi bien être écrite en grec.

Le problème que j'ai rencontré était que la plupart des exemples pour débutants utilisent des "définitions anonymes" alors que vous devriez utiliser un "identifiant de chaîne".

anonyme définit

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


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

définir avec un identifiant de chaîne

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

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

Lorsque vous utilisez define avec un identifiant de chaîne, vous éviterez cette erreur lorsque vous essayez d'utiliser les modules comme ceci:

require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
    moduleOne.helloWorld();
    moduleTwo.helloWorld2();
});
P.Brian.Mackey
la source
(Juste une note pour la postérité) Il y a quelques inconvénients à cette approche, décrits dans la documentation : «les appels define () qui incluent un nom pour le module… sont normalement générés par l'outil d'optimisation… nommer les modules vous-même… rend le modules moins portables… Il est normalement préférable d'éviter de coder dans un nom pour le module et de laisser simplement l'outil d'optimisation graver dans les noms des modules. » … Ainsi que dans ce fil GitHub . Cela semble être la raison pour laquelle la liste du nom est exclue dans les exemples pour débutants.
Mark G.18
10

Selon les documents :

Si vous codez manuellement une balise de script en HTML pour charger un script avec un appel anonyme de define (), cette erreur peut se produire.

Également vu si vous codez manuellement une balise de script en HTML pour charger un script qui a quelques modules nommés, mais essayez ensuite de charger un module anonyme qui finit par avoir le même nom que l'un des modules nommés dans le script chargé manuellement par le balise de script codée.

Enfin, si vous utilisez les plugins de chargeur ou des modules anonymes (modules qui appellent define () sans ID de chaîne) mais n'utilisez pas l'optimiseur RequireJS pour combiner des fichiers ensemble, cette erreur peut se produire. L'optimiseur sait nommer correctement les modules anonymes afin qu'ils puissent être combinés avec d'autres modules dans un fichier optimisé.

Pour éviter l'erreur:

  • Assurez-vous de charger tous les scripts qui appellent define () via l'API RequireJS. Ne codez pas manuellement les balises de script en HTML pour charger des scripts qui contiennent des appels define ().

  • Si vous codez manuellement une balise de script HTML, assurez-vous qu'elle n'inclut que des modules nommés et qu'un module anonyme portant le même nom que l'un des modules de ce fichier n'est pas chargé.

  • Si le problème est l'utilisation de plugins de chargement ou de modules anonymes mais que l'optimiseur RequireJS n'est pas utilisé pour le regroupement de fichiers, utilisez l'optimiseur RequireJS.

AlienWebguy
la source
3
S'agit-il d'un module défini de manière anonyme? github.com/requirejs/example-multipage/blob/master/www/js/app/…
lampadaire
5

Sachez que certaines extensions de navigateur peuvent ajouter du code aux pages. Dans mon cas, j'avais un plugin "Emmet in all textareas" qui gênait mes requireJs. Assurez-vous qu'aucun code supplémentaire n'est ajouté à votre document en l'inspectant dans le navigateur.

Vecteur
la source
5

Les réponses existantes expliquent bien le problème, mais si l'inclusion de vos fichiers de script en utilisant ou avant requireJS n'est pas une option facile en raison du code hérité, une solution de contournement légèrement piratée consiste à supprimer require de la portée de la fenêtre avant votre balise de script, puis à la réintégrer après les mots. Dans notre projet, cela est encapsulé derrière un appel de fonction côté serveur, mais le navigateur voit effectivement ce qui suit:

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

Ce n'est pas le plus soigné mais semble fonctionner et a économisé beaucoup de réfraction.

jcbdrn
la source
5
En fait, ne fais jamais ça. Cela ne fonctionne pas correctement dans IE.
jcbdrn
2
Par intermittence dans IE, les scripts inclus avec requireJS auraient défini des éléments manquants dans leur portée de fenêtre même lorsque la commande require est venue après la restauration de ces variables. Nous n'avons jamais réussi à comprendre pourquoi cela s'est produit, nous avons donc abandonné cette solution piratée.
jcbdrn
2
@jcbdrn Ce n'est pas seulement sur IE. Je l'ai vu se produire sur une autre plateforme. La raison en est que la spécification HTML offre des garanties concernant l'ordre d'exécution des scripts synchrones, mais uniquement par rapport aux autres scripts synchrones . Il ne garantit pas l'exécution de scripts asynchrones par rapport à des scripts synchrones (ou vice-versa). Ainsi, dans le code indiqué dans la réponse ici, il est possible d'exécuter un script asynchrone entre deux scriptéléments quelconques .
Louis
Si vous avez la possibilité de modifier le bundle js que vous importez, vous pouvez simplement emballer le tout comme ceci:(function(){ var define = undefined; // the UMD registration code won't find the global 'define' anymore! // generated content goes here })()
Pete Thorne
2

Ou vous pouvez utiliser cette approche.

  • Ajoutez require.js dans votre base de code
  • puis chargez votre script via ce code

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

Ce qu'il fera, il chargera votre script après le chargement de require.js .

Umar Asghar
la source