2012-10-02 26 views
12

estoy integrando RequireJS en un CMS, así que puse esto en el fondo de mi plantilla de página:Load requireJS module inline the HTML body?

<html> 
<body> 
    {Placeholder1} 
    <script src="scripts/require.js" data-main="scripts/main"></script> 
    {Placeholder2} 
</body> 
</html> 

Luego, en cada página, me gustaría crear una función que aprovecha RequireJS. Así que traté de hacerlo sobre la parte inferior de la página:

<html> 
<body> 
    <h1>Home</h1> 
    <div class="slider">Slider content</div> 

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

    <script type="text/javascript"> 
     require([ 
     'jquery', 
     'utils', 
     'slider' 
     ], function ($, utils, slider) { 
     slider.start(); 
     }); 
    </script> 
</body> 
</html> 

Pero estoy consiguiendo de 404 en jQuery, utilidades y archivos deslizantes js. Parece que no está leyendo mis main.js configuraciones que tengo:

require.config({ 
    paths: { 
     jquery: 'libs/jquery-1.8.1.min', 
     utils: 'libs/utils', 
     slider: 'libs/jquery.slider.min' 
    }, 
    shim: { 
     slider: ['jquery'] 
    } 
}); 

require([ 'utils' ], function (utils) { 
    utils.init(); 
}); 

me trataron RequireJS de carga y principal en la cabeza página, pero tiene resultados inconsistentes de esa manera. Algunas veces jquery, utils y slider se cargarían en el tiempo y otras no. Es como si el "requerir" en línea en la parte inferior de la página no conociera el RequireJS principal en la página o las reglas de dependencia, pero mi punto de ruptura coincide con main.js, así sé que se está llamando. ¿Se debe a que main.js se carga de manera asíncrona, pero mi bloque de "requerir" en línea en la parte inferior de la página se carga en el procesamiento de la página? ¿Cómo puedo evitar esto?

He utilizado RequireJS con éxito antes pero sin un CMS. Siempre utilicé "definir" y los módulos siempre se llamaban asíncronamente, pero nunca tuve que llamar a la función RequireJS en línea de esta manera. ¿Alguna idea sobre la forma correcta de hacer esto?

Respuesta

12

Lo importante aquí es que las opciones de configuración se establecen antes de solicitar cualquier módulo. Como ha identificado correctamente, existen condiciones de carrera que significan que las opciones de configuración en su main.js no se cargan a tiempo. La forma más simple de hacerlo sería poner las opciones de configuración en línea antes de que se cargue el script require.js.

<script> 
var require = { 
    baseUrl: <?= $someVar ?>, 
    paths: { 
     // etc 
    } 
} 
</script> 
<script src="scripts/require.js" data-main="scripts/main"></script> 

final de la página:

<script> 
    require([ 
     'jquery', 
     'utils', 
     'slider' 
     ], function ($, utils, slider) { 
     slider.start(); 
     }); 
</script> 

Ver también How does RequireJS work with multiple pages and partial views?

+1

Un problema con esta configuración es que los recursos pueden cargarse dos veces cuando las secuencias de comandos/archivo principal contienen varios módulos (generalmente el caso cuando se utiliza el optimizador r.js). Esto es especialmente un problema si este es un archivo que no utiliza la definición de require. Supongamos que el archivo 'scripts/main' contiene el módulo LESS JS. Además, suponga que la llamada de requerir en línea también requiere este módulo.Ahora, si se accede a la llamada en línea antes de que se cargue el script principal (como suele ser el caso), el módulo se obtendrá dos veces. ¡Si el contenido no es un módulo AMD, esto puede generar errores! –

6

Parece que lo que está sucediendo es que main.js se está cargando de forma asíncrona, mientras que el requerimiento en línea se llama de inmediato. Esta es la razón por la cual hay resultados inconsistentes. La solución es NO utilizar el atributo principal de datos y llamar al archivo main.js a través de la etiqueta de script debajo de la etiqueta de script require.js.

Todavía se puede determinar la baseUrl del archivo main.js cargado al hacer esto allí:

//DETERMINE BASE URL FROM CURRENT SCRIPT PATH 
var scripts = document.getElementsByTagName("script"); 
var src = scripts[scripts.length-1].src; 
var baseUrl = src.substring(src.indexOf(document.location.pathname), src.lastIndexOf('/')); 

//CONFIGURE LIBRARIES AND DEPENDENCIES VIA REQUIREJS 
require.config({ 
    baseUrl: baseUrl, 
.... 
+0

o usted podría poner su código en línea en el archivo de main.js lugar. O podría poner su camino define en un bloque de código en línea. – dqhendricks

+0

Una de las razones para usar RequireJS es evitar depender de variables globales, así que evite hacerlo. –

+0

@Simon, thx para el consejo. Con los sistemas CMS es difícil evitar esto. En mi opinión, casi todos los CMS están desactualizados. – Basem

Cuestiones relacionadas