101 votes

Requirejs pourquoi et quand utiliser la configuration shim

J'ai lu le document requirejs d'ici API

requirejs.config({
    shim: {
        'backbone': {
            //Ces dépendances de script doivent être chargées avant le chargement
            //de backbone.js
            deps: ['underscore', 'jquery'],
            //Une fois chargé, utilisez le global 'Backbone' comme la
            //valeur du module.
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                //Utiliser une fonction vous permet d'appeler noConflict pour
                //les bibliothèques qui le supportent, et effectuer d'autres nettoyages.
                //Cependant, les plugins pour ces bibliothèques peuvent encore vouloir
                //un global. "this" pour la fonction sera l'objet global.
                //Les dépendances seront passées en tant que
                //arguments de fonction. Si cette fonction renvoie une valeur,
                //alors cette valeur est utilisée comme la valeur d'exportation de module
                //au lieu de l'objet trouvé via la chaîne 'exports'.
                return this.Foo.noConflict();
            }
        }
    }
});

mais je ne comprends pas la partie shim. pourquoi devrais-je utiliser shim et comment devrais-je le configurer, est-ce que je peux obtenir plus de clarification

s'il vous plaît est-ce que quelqu'un peut expliquer avec un exemple pourquoi et quand devrions-nous utiliser shim. merci.

113voto

explunit Points 8317

Une utilisation principale de shim est avec des bibliothèques qui ne prennent pas en charge AMD, mais vous devez gérer leurs dépendances. Par exemple, dans l'exemple Backbone et Underscore ci-dessus : vous savez que Backbone nécessite Underscore, donc supposez que vous avez écrit votre code comme ceci :

require(['underscore', 'backbone']
, function( Underscore, Backbone ) {

    // do something with Backbone

}

RequireJS lancera des requêtes asynchrones pour Underscore et Backbone, mais vous ne savez pas lequel reviendra en premier, il est donc possible que Backbone essaie de faire quelque chose avec Underscore avant qu'il ne soit chargé.

NOTE : cet exemple underscore/backbone a été écrit avant que ces bibliothèques ne prennent en charge AMD. Mais le principe est valable pour toutes les bibliothèques d'aujourd'hui qui ne prennent pas en charge AMD.

Le "hook" init vous permet de faire d'autres choses avancées, par exemple si une bibliothèque exporte normalement deux choses différentes dans l'espace de noms global mais que vous voulez les redéfinir sous un seul espace de noms. Ou peut-être que vous voulez effectuer des patchs sur des méthodes de la bibliothèque que vous chargez.

Plus d'informations :

0 votes

Comme dans votre exemple de code, les balises Underscore et Backbone sont utilisées normalement ici, que fait shim dans ce cas ? Puis-je utiliser require( function() { _.extend({}); }) ? Est-ce qu'il comprend _ ?

0 votes

"RequireJS lancera des requêtes asynchrones pour Underscore et Backbone" -> Est-il possible d'empêcher cela, dans le cas où la bibliothèque est déjà chargée ?

1 votes

@Codii oui, si la bibliothèque est déjà chargée, elle ne lancera pas une autre demande de serveur, mais l'objectif de RequireJS est que votre code n'ait pas à se soucier de s'il/héa que cela se produise. Peut-être commencer une nouvelle question pour votre cas d'utilisation particulier?

66voto

nalinc Points 6716

Conformément à la documentation de l'API RequireJS, shim vous permet de

Configurer les dépendances, les exports et l'initialisation personnalisée pour les scripts plus anciens et traditionnels, appelés "globals du navigateur", qui n'utilisent pas define() pour déclarer les dépendances et définir une valeur de module.

- Configuration des dépendances

Disons que vous avez 2 modules JavaScript (moduleA et moduleB) et que l'un d'eux (moduleA) dépend de l'autre (moduleB). Les deux sont nécessaires pour votre propre module, donc vous spécifiez les dépendances dans require() ou define()

require(['moduleA','moduleB'],function(A,B ) {
    ...
}

Mais comme require lui-même suit AMD, vous ne savez pas lequel sera récupéré en premier. C'est là que le shim intervient pour vous sauver.

require.config({
    shim:{
       moduleA:{
         deps:['moduleB']
        } 
    }

})

Cela garantira que le moduleB soit toujours récupéré avant que le moduleA ne soit chargé.

- Configuration des exports

Shim export indique à RequireJS quel membre de l'objet global (la fenêtre, en supposant que vous soyez dans un navigateur, bien sûr) est la véritable valeur du module. Supposons que le moduleA s'ajoute à la window en tant que 'modA' (tout comme jQuery et underscore le font en tant que $ et _ respectivement), alors nous définissons notre valeur d'export comme 'modA'.

require.config({
    shim:{
       moduleA:{
         exports:'modA'
        } 
    }

Cela donnera à RequireJS une référence locale à ce module. Le modA global continuera également d'exister sur la page.

- Initialisation personnalisée pour les anciens scripts "globals du navigateur"

C'est probablement la fonctionnalité la plus importante de la configuration shim qui nous permet d'ajouter des scripts 'global du navigateur', des scripts 'non-AMD' (qui ne suivent pas non plus de modèle modulaire) en tant que dépendances dans notre propre module.

Supposons que le moduleB soit un simple javascript ancien avec seulement deux fonctions funcA() et funcB().

function funcA(){
    console.log("this is function A")
}
function funcB(){
    console.log("this is function B")
}

Bien que ces deux fonctions soient disponibles dans la portée window, RequireJS nous recommande de les utiliser via leur identifiant/global pour éviter les confusions. Donc, en configurant le shim comme suit

shim: {
    moduleB: {
        deps: ["jquery"],
        exports: "funcB",
        init: function () {
            return {
                funcA: funcA,
                funcB: funcB
            };
        }
    }
}

La valeur de retour de la fonction init est utilisée comme valeur d'exportation de module au lieu de l'objet trouvé via la chaîne 'exports'. Cela nous permettra d'utiliser funcB dans notre propre module comme ci-dessous

require(["moduleA","moduleB"], function(A, B){
    B.funcB()
})

J'espère que cela a été utile.

-2voto

Rachman Anwar Points 11

Vous devez ajouter des chemins dans requirejs.config pour déclarer, par exemple:

requirejs.config({
    paths: {
          'underscore' : '.../exemple/XX.js' // votre fichier JavaScript
          'jquery' : '.../exemple/jquery.js' // votre fichier JavaScript
    }
    shim: {
        'backbone': {
            deps: ['underscore', 'jquery'],
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                return this.Foo.noConflict();
            }
        }
    }
});

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