Requirejs por que y cuando usar shim config

97

Leí el documento requirejs desde aquí API

requirejs.config({
    shim: {
        'backbone': {
            //These script dependencies should be loaded before loading
            //backbone.js
            deps: ['underscore', 'jquery'],
            //Once loaded, use the global 'Backbone' as the
            //module value.
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                //Using a function allows you to call noConflict for
                //libraries that support it, and do other cleanup.
                //However, plugins for those libraries may still want
                //a global. "this" for the function will be the global
                //object. The dependencies will be passed in as
                //function arguments. If this function returns a value,
                //then that value is used as the module export value
                //instead of the object found via the 'exports' string.
                return this.Foo.noConflict();
            }
        }
    }
});

pero no voy a recibir calzas . ¿Por qué debería usar shim y cómo debo configurar? ¿Puedo obtener más aclaraciones?

por favor, ¿alguien puede explicar con un ejemplo por qué y cuándo deberíamos usar calzas? Gracias.

Anil Gupta
fuente

Respuestas:

110

Un uso principal de shim es con bibliotecas que no son compatibles con AMD, pero es necesario administrar sus dependencias. Por ejemplo, en el ejemplo anterior de Backbone y Underscore: sabe que Backbone requiere Underscore, así que suponga que escribió su código así:

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

    // do something with Backbone

}

RequireJS iniciará solicitudes asincrónicas para Underscore y Backbone, pero no sabe cuál volverá primero, por lo que es posible que Backbone intente hacer algo con Underscore antes de que se cargue.

NOTA: este ejemplo de subrayado / columna vertebral se escribió antes de que ambas bibliotecas admitieran AMD. Pero el principio es válido para cualquier biblioteca actual que no sea compatible con AMD.

El gancho "init" le permite hacer otras cosas avanzadas, por ejemplo, si una biblioteca normalmente exportaría dos cosas diferentes al espacio de nombres global pero desea redefinirlas en un solo espacio de nombres. O tal vez desee hacer un parche de mono en un método en la biblioteca que está cargando.

Más antecedentes:

explotar
fuente
Como su código de ejemplo, el Underscorey Backboneaquí se usa como el normal, ¿qué shimhago en este caso? ¿Puedo usar require( function() { _.extend({}); })? ¿Entiende _?
Stiger
"RequireJS iniciará solicitudes asincrónicas tanto para Underscore como para Backbone" -> ¿Es posible evitar esto, en el caso de que la biblioteca ya esté cargada?
Codii
1
@Codii correcto, si la biblioteca ya está cargada, no iniciará otra solicitud de servidor, pero el punto de RequireJS es que su código no necesita preocuparse por si o cómo sucede eso. ¿Quizás comenzar una nueva pregunta para su caso de uso particular?
Explunit el
63

Según la documentación de la API RequireJS, shim te permite

Configure las dependencias, las exportaciones y la inicialización personalizada para los scripts "globales del navegador" tradicionales más antiguos que no usan define () para declarar las dependencias y establecer un valor de módulo.

- Configurar dependencias

Digamos que tiene 2 módulos javascript (moduleA y moduleB) y uno de ellos (moduleA) depende del otro (moduleB). Ambos son necesarios para su propio módulo, por lo que especifica las dependencias en require () o define ()

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

Pero dado que el propio requerimiento sigue a AMD, no tiene idea de cuál se buscaría antes. Aquí es donde Shim viene al rescate.

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

})

Esto aseguraría que el módulo B siempre se recupere antes de que se cargue el módulo A.

- Configurar exportaciones

Shim export le dice a RequireJS qué miembro del objeto global (la ventana, asumiendo que estás en un navegador, por supuesto) es el valor real del módulo. Digamos que moduleA se agrega a sí mismo windowcomo 'modA' (al igual que jQuery y el subrayado lo hacen como $ y _ respectivamente), luego hacemos que nuestro valor de exportación sea 'modA'.

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

Le dará a RequireJS una referencia local a este módulo. El modA global también existirá en la página.

-Inicialización personalizada para scripts "globales del navegador" más antiguos

Esta es probablemente la característica más importante de la configuración de shim que nos permite agregar scripts 'global del navegador', 'que no son de AMD' (que tampoco siguen un patrón modular) como dependencias en nuestro propio módulo.

Digamos que moduleB es un javascript antiguo y simple con solo dos funciones funcA () y funcB ().

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

Aunque ambas funciones están disponibles en el ámbito de la ventana, RequireJS nos recomienda usarlas a través de su identificador / identificador global para evitar confusiones. Así que configurando la cuña como

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

El valor de retorno de la función init se utiliza como valor de exportación del módulo en lugar del objeto encontrado a través de la cadena 'exportaciones'. Esto nos permitirá usar funcB en nuestro propio módulo como

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

Espero que esto haya ayudado.

nalinc
fuente
3
¡Fácil de comprender! Una pregunta: en el último ejemplo, ¿se ignora simplemente la propiedad "exportaciones"?
Niko Bellic
No, no está siendo ignorado. Si la propiedad "exporta" se hubiera ignorado en el último ejemplo, entonces el objeto que pasa como parámetro ('B' en este caso) no estaría definido ya que moduleB NO es compatible con AMD y no habría devuelto un objeto para que RequireJS lo use ( por lo tanto, 'B.funcB' no funcionaría).
nalinc
Hmm. Pensé que el valor de la exportación sería anulado por el objeto que se devuelve en la función init. Entonces, el parámetro B sería el objeto {funcA: funcA, funcB: funcB}, no simplemente funcB por sí mismo. ¿No es esto cierto?
Niko Bellic
4
Niko Bellic tiene razón, se ignora la exportación (acabo de probar eso). El objeto B es el objeto devuelto por la función especificada en la parte 'init'. Si eliminó la parte 'init', el objeto B se convertiría en la función funcB, por lo que simplemente haría B () en lugar de B.funcB (). Y obviamente funcA se volvería inaccesible en ese caso.
user4205580
-2

Debe agregar rutas en requirejs.config para declarar, ejemplo:

requirejs.config({
    paths: {
          'underscore' : '.../example/XX.js' // your JavaScript file
          'jquery' : '.../example/jquery.js' // your JavaScript file
    }
    shim: {
        'backbone': {
            deps: ['underscore', 'jquery'],
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                return this.Foo.noConflict();
            }
        }
    }
});
Rachman Anwar
fuente
1
Esta respuesta es un volcado de código que no explica "por qué y cuándo usar shim config". Si edita su respuesta para proporcionar una explicación, asegúrese de agregar algo nuevo, que no esté ya cubierto por respuestas anteriores
Louis
copiar y pegar sin ningún comentario positivo
william.eyidi
debe haber una coma antes de shim:
Scott