37 votes

Shim Twitter Bootstrap pour RequireJS

Le RequireJS docs disent que, pour prendre en charge les anciennes versions d'IE, vous devez configurer enforceDefine: true.

Donc, si vous voulez en charge d'Internet Explorer, de capture des erreurs de chargement, et ont code modulaire, soit directement define() appels ou cale de config, toujours ensemble enforceDefine pour être vrai. Voir la section suivante pour un exemple.

REMARQUE: Si vous ne définissez enforceDefine: c'est vrai, et que vous utilisez des données-main="" pour charger vos principales JS module, alors que les principaux JS module doit appeler define() au lieu de require() pour charger le code dont il a besoin. Le principal JS module peut encore appeler exiger/requirejs pour définir config valeurs, mais pour le chargement des modules, il doit utiliser define().

Depuis Twitter Bootstrap n'est pas un AMD module, j'ai besoin de cale pour qu'il fonctionne. C'est de cette façon que je le configure;

<script type="text/javascript">
    var require = {
        paths: {
            "bootstrap": "../bootstrap",
            "jquery": "../jquery-1.8.2"
        },
        shim: {
            "bootstrap": ["jquery"]
        },
        enforceDefine: true
    };
</script>

Plus tard, quand mon module veut bootstrap comme une dépendance, j'ai toujours un message d'erreur;

Error: No define call for bootstrap

http://requirejs.org/docs/errors.html#nodefine

Si j'ai bien compris la doc correctement, enforceDefinedoit ignorer les cales, mais il ne l'est pas.

Ce que je fais mal ici?

37voto

Karolis Points 1500

Selon les docs que l'erreur est levée si le Script "faisait partie d'une cale de config que spécifié une chaîne globale de la propriété, qui peut être vérifiée pour le chargement, et que l'enregistrement a échoué."

Pour corriger cela, vous devez ajouter la valeur des exportations dans la cale config de sorte que RequireJS pouvez vérifier si le script a été chargé avec succès. En cas de Bootstrap c'est un peu difficile comme Bootstrap n'est pas "exporter" un se trouve dans la variable globale seulement un tas de plugins jquery, mais vous pouvez utiliser l'un de ces plugins, comme une valeur à l'exportation par exemple, $.fn.popover:

{
    paths: {
        "bootstrap": "../bootstrap",
        "jquery": "../jquery-1.8.2"
    },
    shim: {
        "bootstrap": {
          deps: ["jquery"],
          exports: "$.fn.popover"
        }
    },
    enforceDefine: true
}

14voto

phammer Points 832

Au lieu de faire de la magie avec la cale, j'ai converti le fichier de bootstrap JS dans un module:

define([ "jquery" ], function($) {
  // bootstrap JS code
});

Tout le reste je l'ai trouvé dans les forums et sur stackoverflow ne fonctionne pas pour moi, parce que je me jQuery par le CDN. Je suppose parce que j'ai frappé à la question, telle que décrite dans la doc sur requireJS http://requirejs.org/docs/api.html

Ne pas mélanger CDN de chargement avec cale de config dans un build. Exemple de scénario: vous charger jQuery à partir de la CAN mais l'utilisation de la cale de config pour charger quelque chose comme le stock de la version de base qui dépend de jQuery. Lorsque vous ne la construction, assurez-vous de l'inclure jQuery dans le construit fichier et ne se charge pas à partir de la CAN. Sinon, épine Dorsale est insérée dans le haut du fichier et il l'exécute avant la CAN-chargé de jQuery se charge. C'est parce que la cale config juste délais de chargement des fichiers jusqu'à ce que les dépendances sont chargés, mais ne pas faire d'auto-habillage de définir. Après une génération, les dépendances sont déjà intégrées à la cale de config ne peut pas retarder l'exécution de la non-define()'d code jusqu'à ce que plus tard. define()'d les modules fonctionnent avec le CDN chargé de code après un build parce que ils s'enrouler correctement leur source dans définir usine de fonction ne pas exécuter jusqu'à ce que les dépendances sont chargés. Donc la leçon: cale de config est un arrêt de l'écart de mesure pour les non-modulaire code, le code de legs. define()'d les modules sont mieux.

La conversion du fichier d'amorce dans un ordinaire AMD module et le retrait de la cale de config résolu pour moi. Seul inconvénient: vous ne pouvez pas récupérer des fichiers d'amorce à partir du bootstrap CDN.

11voto

lexeme Points 620

J'utilise cette configuration dans mon projet:

startup.js

 require.config({
    paths: {
        /* other paths are omitted */
        'bootstrap': '../libs/bootstrap'
    },
    shim: {
        'bootstrap/bootstrap-slider': { deps: ['jquery'], exports: '$.fn.slider' }, 
        'bootstrap/bootstrap-affix': { deps: ['jquery'], exports: '$.fn.affix' },
        'bootstrap/bootstrap-alert': { deps: ['jquery'], exports: '$.fn.alert' },
        'bootstrap/bootstrap-button': { deps: ['jquery'], exports: '$.fn.button' },
        'bootstrap/bootstrap-carousel': { deps: ['jquery'], exports: '$.fn.carousel' },
        'bootstrap/bootstrap-collapse': { deps: ['jquery'], exports: '$.fn.collapse' },
        'bootstrap/bootstrap-dropdown': { deps: ['jquery'], exports: '$.fn.dropdown' },
        'bootstrap/bootstrap-modal': { deps: ['jquery'], exports: '$.fn.modal' },
        'bootstrap/bootstrap-popover': { deps: ['jquery'], exports: '$.fn.popover' },
        'bootstrap/bootstrap-scrollspy': { deps: ['jquery'], exports: '$.fn.scrollspy'        },
        'bootstrap/bootstrap-tab': { deps: ['jquery'], exports: '$.fn.tab' },
        'bootstrap/bootstrap-tooltip': { deps: ['jquery'], exports: '$.fn.tooltip' },
        'bootstrap/bootstrap-transition': { deps: ['jquery'], exports: '$.support.transition' },
        'bootstrap/bootstrap-typeahead': { deps: ['jquery'], exports: '$.fn.typeahead'  },
    }
});

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

alors dans mon code j'utilise ceci:

 define(['jquery', 'underscore', 'backbone', 'text!templates/photos-list.html'], function($, _, Backbone, html) {
    var PhotosListView = Backbone.View.extend({
        viewImageFullscreen: function(e) {
            e.preventDefault();
            /* bla-bla-bla ... */
            require(['bootstrap/bootstrap-modal', 'text!templates/photo-modal.html'], function(modal, htmlModal) {
                 var modalTemplate = _.template(htmlModal, options);
                 $('body').append(modalTemplate);

                 // setup
                 $(selector + '_modal').modal({
                     backdrop: true,
                     keyboard: true,
                     show: false
                 }).css({
                     'width': function() { return ($(document).width() * 0.55) + 'px'; },
                     'margin-left': function() { return -($(this).width() * 0.5); }
                 });

                 // trigger `modal` 
                 $(selector + '_modal').modal('show');
             }); // require() call
         // ...
 

4voto

Jasper Moelker Points 439

@lexeme & @benjaminbenben Pourquoi ne pas intégrer ce concept dans un plug-in RequireJS qui crée le shim, requiert jQuery et renvoie également jQuery afin que vous n'ayez pas besoin de l'inclure manuellement?

Pour utiliser un composant d'amorçage, vous utiliseriez simplement:

 define(['bootstrap!tooltip'], function($){
  $('[data-toggle="tooltip"]').tooltip();
});
 

Et vous utiliseriez ce require-bootstrap-plugin pour le faire fonctionner.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X