2012-10-02 5 views
12

Je suis dans un RequireJS intègrent CMS donc je mis cela sur le fond de mon modèle de page:Charger le module requireJS dans le corps HTML?

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

Puis sur chaque page, je voudrais créer une fonction qui tire parti RequireJS. J'ai donc essayé de placer ce au bas de la page:

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

mais je reçois 404 est sur jquery, utils et les fichiers de curseur. Il semble que ce ne lit pas mes main.js configs que j'ai:

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

J'ai essayé RequireJS de chargement et principal dans la tête de page, mais a obtenu des résultats incohérents de cette façon. Parfois, jquery, utils et slider seraient chargés à temps et d'autres fois non. C'est comme si le "require" en ligne au bas de la page ne connaissait pas la page principale RequireJS ou les règles de dépendances, mais mon point d'arrêt arrive dans main.js, donc je sais qu'il est appelé. Est-ce parce que main.js est chargé de manière asynchrone mais que mon bloc "require" en ligne au bas de la page est chargé sur le rendu de la page? Comment puis-je contourner cela?

J'ai utilisé RequireJS avec succès avant mais sans CMS. J'ai toujours utilisé "define" et j'avais des modules toujours appelés de façon asynchrone, mais je n'ai jamais eu besoin d'appeler la fonction RequireJS en ligne comme ceci. Des idées sur la bonne façon de le faire?

Répondre

12

L'important est ici que les options de configuration sont définies avant tous les modules sont demandés. Comme vous l'avez correctement identifié, il existe des conditions de concurrence qui signifient que les options de configuration de votre main.js ne sont pas chargées à temps. Le moyen le plus simple serait de placer les options de configuration en ligne avant que le script require.js ne soit chargé.

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

plus bas de la page:

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

Voir aussi How does RequireJS work with multiple pages and partial views?

+1

Un problème avec cette configuration est que les ressources peuvent être chargées deux fois lorsque le script/fichier principal contient plusieurs modules (généralement le cas lorsque l'optimiseur r.js est utilisé). C'est particulièrement un problème si c'est un fichier qui n'utilise pas require. Supposons que le fichier 'scripts/main' contient le module LESS JS. En outre, supposons que l'appel inline nécessite également ce module.Maintenant, si l'on accède à l'appel en ligne avant que le script principal soit chargé (ce qui est généralement le cas), le module sera obtenu deux fois. Si le contenu n'est pas un module AMD, cela peut entraîner des erreurs! –

6

Il semble que ce qui se passe est que le main.js est chargé de manière asynchrone alors que le besoin en ligne est appelé immédiatement. C'est pourquoi il y a des résultats incohérents. La solution est de NE PAS utiliser l'attribut data-main et d'appeler le fichier main.js via une balise de script située sous la balise script require.js.

Vous pouvez toujours déterminer le baseUrl du fichier chargé main.js en faisant cela là-dedans:

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

Ou vous pourriez mettre votre code en ligne dans le fichier main.js à la place. Ou vous pourriez mettre votre chemin définit dans un bloc de code en ligne. – dqhendricks

+0

L'une des raisons d'utiliser RequireJS est d'éviter de se fier aux variables globales, alors évitez de le faire. –

+0

@Simon, merci pour le conseil. Avec les systèmes CMS, il est difficile d'éviter cela. À mon avis, presque tous les CMS sont obsolètes. – Basem

Questions connexes