Juste pour dissiper toute confusion autour de exports
, il est supposé que toute la cale de la bibliothèque s'attache à une propriété pour le contexte global (window
ou root
), ou modifie un déjà existant mondiale de la propriété (par exemple, un plugin jQuery). Lorsque requireJS obtient la commande pour charger un calée dépendance, il examine le contexte global pour un bien correspondant à la exports
de la valeur de la cale de config, et si il le trouve, il la retourne comme valeur de ce module. Si il ne le trouve pas, alors il charge le script associé, attend à ce qu'il exécute, puis trouve le symbole mondial et le renvoie.
Un fait important à retenir est que, à moins que la cale config contient un exports
de la valeur, tout init
méthode sur cette config ne sera PAS exécuté. La dépendance chargeur doit localiser une valeur pour le module (qui est ce que l' exports
précise) avant que le module peut être initialisé, ce qui est pourquoi la propriété est requis s'il y a une cale init
de ce module.
mise à jour: j'ai aussi besoin de rappeler que si le module en question exige define
de n'importe où, cale config que vous avez pour ce module sera ignoré. En fait, cela m'a causé quelques maux de tête parce que je voulais utiliser la cale de config à l'appel de jQuery jQuery.noConflict(true)
méthode de l'onu-globify jQuery et le garder à portée seulement les modules qui en ont besoin, mais j'ai fini par avoir à créer une jquery-noconflict.js fichier qui n'a, a 'jquery' pathed à l'jquery-noconflict.js fichier, de modifier notre copie locale de jQuery afin qu'il définit lui-même comme "jQuery 1.9.1' au lieu de simplement 'jQuery', et ont jquery-noconflict.js besoin d'jQuery 1.9.1 " au lieu de jQuery. J'ai essayé d'utiliser l' map
config pour obtenir autour de la nécessité de modifier le jQuery source, mais ne parvenais pas à le faire fonctionner.
mise à jour 2: Une récente question sur le requireJS groupe google m'a fait réaliser que mon explication peut être un peu trompeur, donc je tiens à le préciser. RequireJS ne ré-utiliser un calée dépendance si il a été chargé par requireJS au moins une fois. C'est-à-dire, si vous avez simplement un <script>
tag sur la page d'hébergement (disons, par exemple, le trait de soulignement), comme ceci:
<script src='lib/underscore.js'></script>
<script src='lib/require.js' data-main='main.js'></script>
...et vous avez quelque chose comme ceci dans votre requireJS config:
paths: {
'underscore': 'lib/underscore'
},
shim: {
'underscore': {
exports: '_'
}
}
Puis la première fois, vous n' define(['underscore'], function (_) {});
ou var _ = require('underscore');
, RequireJS re-charger le trait de soulignement de la bibliothèque plutôt que de ré-utilisation définies précédemment window._
, car autant que requireJS sait, vous n'avez jamais chargé trait de soulignement avant. Bien sûr, il peut vérifier pour voir si _
est déjà défini sur la racine de la portée, mais il n'a aucun moyen de vérifier que l' _
qui est déjà là est le même que celui défini dans votre paths
config. Par exemple, les deux prototype
et jquery
astreignent window.$
par défaut, et si requireJS suppose que 'window.$' jQuery est quand il est en fait un prototype, vous allez être dans une mauvaise situation.
Tout cela signifie que si vous mix-and-match de script de chargement des styles comme ça, votre page se retrouver avec quelque chose comme ceci:
<script src='lib/underscore.js'></script>
<script src='lib/require.js' data-main='main.js'></script>
<script src='lib/underscore.js'></script>
Où le deuxième trait de soulignement instance, qui est chargé par requireJS.
Fondamentalement, une bibliothèque doit être chargé via requireJS pour requireJS avoir connaissance. Cependant, la prochaine fois vous avez besoin de souligner, requireJS va "hey, j'ai déjà chargé, il suffit donc de la main tout ce qui l' exports
valeur et ne vous inquiétez pas sur le chargement d'un autre script."
Cela signifie que vous avez deux options réelles. Est ce que je considère être un anti-modèle: il suffit de ne pas utiliser de requireJS pour exprimer les dépendances pour les mondiaux de scripts. C'est, aussi longtemps que la bibliothèque s'attache à un mondial à la racine de contexte, vous serez en mesure d'y accéder, même si cette dépendance n'est pas explicitement requis. Vous pouvez voir pourquoi c'est un anti-pattern - vous avez fondamentalement juste d'éliminer la plupart des avantages de l'utilisation d'un AMD chargeur (explicite dépendance de l'inscription et de la portabilité).
L'autre, la meilleure option est d'utiliser requireJS pour charger tout, au point que la seule balise de script, vous devez créer vous-même est celui qui a initialement charges requireJS. Vous pouvez utiliser des cales, mais 95% du temps, c'est pas vraiment difficile d'ajouter un AMD wrapper pour le script à la place. Il pourrait prendre un peu plus de travail pour convertir tous vos non-AMD bibliothèques AMD compatible, mais une fois que vous avez fait un ou deux, cela devient beaucoup plus facile - je peux prendre un médicament générique jQuery plugin et de le convertir à une AMD module en moins d'une minute. C'est généralement juste une question d'ajouter
define(['jquery'], function (jQuery) {
en haut, et
return jQuery;
});
au bas. La raison pour laquelle j'ai 'jquery' mappage jQuery
plutôt que d' $
, c'est que j'ai remarqué que la plupart des plugins de ces jours sont enveloppés dans une fermeture comme ceci:
(function ($) {
// plugin code here
})(jQuery);
Et c'est une bonne idée de prêter attention à la portée voulue. Vous pouvez certainement carte 'jquery' à $
directement si, en supposant que le plugin n'est pas en attendant de trouver jQuery
au lieu de $
. C'est juste la base d'AMD wrapper - plus complexes généralement essayer de détecter ce type de chargeur est utilisé (commonJS vs AMD vs régulière ol' globals) et utiliser une autre méthode de chargement en fonction du résultat. Vous pouvez trouver des exemples de ce assez facilement avec quelques secondes sur google.