Módulo define () anónimo no coincidente

129

Recibo este error cuando busco mi aplicación web por primera vez (generalmente en un navegador con caché deshabilitada).

Error: módulo define () anónimo no coincidente: función (requiere) {

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

¿Alguien sabe exactamente qué significa este error y por qué está sucediendo?

archivo fuente , una breve discusión al respecto en la página de problemas de github

Adonis K. Kakoulidis
fuente

Respuestas:

142

Como dijo AlienWebguy, según los documentos, require.js puede explotar si

  • Tiene una definición anónima (" módulos que llaman a define () sin ID de cadena ") en su propia etiqueta de script (supongo que en realidad significan en cualquier parte del alcance global)
  • Tienes módulos que tienen nombres en conflicto
  • Utiliza complementos de cargador o módulos anónimos, pero no utiliza el optimizador de require.js para agruparlos

Tuve este problema al incluir paquetes construidos con browserify junto con los módulos require.js. La solución fue:

A. cargue los paquetes independientes no require.js en las etiquetas de script antes de cargar require.js, o

B. cárguelos usando require.js (en lugar de una etiqueta de script)

BT
fuente
2
los nombres en conflicto son comunes
Julio Marins
1
Otra posible solución, en algunos casos especiales con módulos anónimos, es sobrescribir la función requirejs.onError para evitar la excepción de error predeterminada generada por requirejs que detiene la ejecución de módulos o códigos sucesivos.
xtrm
1
Acabo de agregar una solicitud de extracción ( github.com/requirejs/requirejs/pull/1763 ) para relajar ese caso exacto. Creo que es un problema muy común en estos días.
Bob S
1
¡Gracias por decirme que los cargue antes! No sé por qué este consejo no está en la documentación de requirejs ... Ahí es donde la pila es útil
Tobias Feil
14

Tuve este error porque incluí el archivo requirejs junto con otras bibliotecas incluidas directamente en una etiqueta de script. Esas bibliotecas (como lodash) usaron una función de definición que estaba en conflicto con la definición de require. El archivo requirejs se estaba cargando de forma asíncrona, por lo que sospecho que la definición de require se definió después de la definición de las otras bibliotecas, de ahí el conflicto.

Para deshacerse del error, incluya todos sus otros archivos js utilizando requirejs.

eloone
fuente
Resultó que muchas bibliotecas hacen tal cosa, o al menos usan / exportan dicha función. Aconsejaré a todos, si usan require, importen todo con require :)
Andrey Popov
12

Al comenzar con reactjs me encontré con el problema y, como principiante, los documentos también pueden estar escritos en griego.

El problema con el que me topé fue que la mayoría de los ejemplos para principiantes usan "definiciones anónimas" cuando deberías usar un "id de cadena".

anónimo define

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


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

definir con id de cadena

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

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

Cuando use define con una identificación de cadena , evitará este error cuando intente usar los módulos de esta manera:

require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
    moduleOne.helloWorld();
    moduleTwo.helloWorld2();
});
P.Brian.Mackey
fuente
(Sólo una nota para la posteridad) No son algunos aspectos negativos de este enfoque, que se describen en los documentos : “define () llama que incluyen un nombre para el módulo ... normalmente se genera por la herramienta de optimización ... nam [ing] módulos de ti mismo ... hace que el módulos menos portátiles ... Por lo general, es mejor evitar codificar un nombre para el módulo y simplemente dejar que la herramienta de optimización grabe los nombres de los módulos ". ... así como en este hilo de GitHub . Esta parece ser la razón por la cual la inclusión del nombre se excluye en los ejemplos para principiantes.
Mark G.
10

Por los documentos :

Si codifica manualmente una etiqueta de script en HTML para cargar un script con una llamada anónima define (), este error puede ocurrir.

También se ve si codifica manualmente una etiqueta de script en HTML para cargar un script que tiene algunos módulos con nombre, pero luego intenta cargar un módulo anónimo que termina teniendo el mismo nombre que uno de los módulos con nombre en el script cargado manualmente etiqueta de script codificada

Finalmente, si usa los complementos del cargador o los módulos anónimos (módulos que llaman a define () sin ID de cadena) pero no usa el optimizador RequireJS para combinar archivos, este error puede ocurrir. El optimizador sabe cómo nombrar módulos anónimos correctamente para que puedan combinarse con otros módulos en un archivo optimizado.

Para evitar el error:

  • Asegúrese de cargar todos los scripts que invocan define () a través de la API RequireJS. No codifique manualmente las etiquetas de secuencia de comandos en HTML para cargar secuencias de comandos que tengan llamadas define () en ellas.

  • Si codifica manualmente una etiqueta de script HTML, asegúrese de que solo incluya módulos con nombre y que no se cargue un módulo anónimo que tendrá el mismo nombre que uno de los módulos en ese archivo.

  • Si el problema es el uso de complementos del cargador o módulos anónimos, pero el optimizador RequireJS no se usa para la agrupación de archivos, use el optimizador RequireJS.

AlienWebguy
fuente
3
¿Es este un módulo definido anónimamente? github.com/requirejs/example-multipage/blob/master/www/js/app/…
streetlight
5

Tenga en cuenta que algunas extensiones del navegador pueden agregar código a las páginas. En mi caso, tenía un plugin "Emmet en todas las áreas de texto" que se equivocaba con mis requireJs. Asegúrese de que no se agregue ningún código adicional a su documento inspeccionándolo en el navegador.

Vector
fuente
5

Las respuestas existentes explican bien el problema, pero si incluir sus archivos de script usando o antes requireJS no es una opción fácil debido a un código heredado, una solución un tanto extravagante es eliminar require del alcance de la ventana antes de su etiqueta de script y luego restablecerlo después. En nuestro proyecto, esto está envuelto detrás de una llamada de función del lado del servidor, pero efectivamente el navegador ve lo siguiente:

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

No es el más bonito, pero parece funcionar y ha ahorrado una gran cantidad de refractarización.

jcbdrn
fuente
55
En realidad nunca hagas esto. No funciona correctamente en IE.
jcbdrn
2
De manera intermitente en IE, los scripts incluidos con requireJS habrían definido faltantes en el alcance de su ventana incluso cuando el comando require vino después de que se restauraron esas variables. Nunca logramos entender por qué ocurrió esto, así que abandonamos esta solución hacky.
jcbdrn
2
@jcbdrn No es solo en IE. Lo he visto suceder en otra plataforma. La razón es que la especificación HTML ofrece garantías con respecto al orden de ejecución de los scripts síncronos, pero solo en relación con otros síncronos . No garantiza la ejecución de scripts asíncronos en relación con uno síncrono (o viceversa). Entonces, en el código que se muestra en la respuesta aquí, es posible ejecutar un script asincrónico entre dos scriptelementos.
Louis
Si tiene la capacidad de editar el paquete js que está importando, puede envolver todo de esta manera:(function(){ var define = undefined; // the UMD registration code won't find the global 'define' anymore! // generated content goes here })()
Pete Thorne
2

O puedes usar este enfoque.

  • Agregue require.js en su base de código
  • luego carga tu script a través de ese código

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

Lo que hará cargará su script después de cargar require.js .

Umar Asghar
fuente