Erforderlich, warum und wann Shim Config verwendet werden soll

97

Ich habe das requirejs- Dokument von hier API gelesen

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

aber ich bin nicht immer Shim Teil davon. Warum sollte ich Shim verwenden und wie sollte ich konfigurieren? Kann ich mehr Klarheit bekommen?

Bitte kann jemand anhand eines Beispiels erklären, warum und wann wir Shim verwenden sollten. Vielen Dank.

Anil Gupta
quelle

Antworten:

110

Shim wird hauptsächlich in Bibliotheken verwendet, die AMD nicht unterstützen, deren Abhängigkeiten Sie jedoch verwalten müssen. Beispiel im obigen Beispiel für Backbone und Unterstrich: Sie wissen, dass für Backbone Unterstrich erforderlich ist. Nehmen wir also an, Sie haben Ihren Code folgendermaßen geschrieben:

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

    // do something with Backbone

}

RequireJS startet asynchrone Anforderungen für Underscore und Backbone, aber Sie wissen nicht, welche zuerst zurückkommt, sodass Backbone möglicherweise versucht, etwas mit Underscore zu tun, bevor es geladen wird.

HINWEIS: Dieses Unterstrich- / Backbone-Beispiel wurde geschrieben, bevor beide Bibliotheken AMD unterstützten. Das Prinzip gilt jedoch für alle Bibliotheken, die AMD heute nicht unterstützen.

Mit dem Hook "init" können Sie andere erweiterte Aufgaben ausführen, z. B. wenn eine Bibliothek normalerweise zwei verschiedene Aufgaben in den globalen Namespace exportiert, diese jedoch unter einem einzigen Namespace neu definieren möchten. Oder vielleicht möchten Sie ein Affen-Patching für eine Methode in der Bibliothek durchführen, die Sie laden.

Mehr Hintergrund:

explunit
quelle
Wie Ihr Beispielcode, der Underscoreund Backbonehier wie der normale verwendet, was shimtun Sie in diesem Fall? Kann ich verwenden require( function() { _.extend({}); })? Versteht es _?
Stiger
"RequireJS startet asynchrone Anforderungen für Underscore und Backbone" -> Kann dies verhindert werden, falls die Bibliothek bereits geladen ist?
Codii
1
@Codii richtig, wenn die Bibliothek bereits geladen ist, wird keine weitere Serveranforderung ausgelöst, aber der Punkt von RequireJS ist, dass Ihr Code sich nicht darum kümmern muss, ob / wie dies geschieht. Beginnen Sie vielleicht eine neue Frage für Ihren speziellen Anwendungsfall?
Explunit
63

Gemäß der RequireJS-API-Dokumentation können Sie mit shim

Konfigurieren Sie die Abhängigkeiten, Exporte und benutzerdefinierten Initialisierungen für ältere, traditionelle "Browser-Globals" -Skripte, die nicht define () verwenden, um die Abhängigkeiten zu deklarieren und einen Modulwert festzulegen.

- Abhängigkeiten konfigurieren

Nehmen wir an, Sie haben 2 Javascript-Module (Modul A und Modul B) und eines davon (Modul A) hängt vom anderen ab (Modul B). Beide sind für Ihr eigenes Modul erforderlich, sodass Sie die Abhängigkeiten in require () oder define () angeben.

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

Aber da sich AMD selbst folgen muss, haben Sie keine Ahnung, welches früh abgeholt wird. Hier kommt Shim zur Rettung.

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

})

Dies würde sicherstellen, dass Modul B immer abgerufen wird, bevor Modul A geladen wird.

- Exporte konfigurieren

Der Shim-Export teilt RequireJS mit, welches Mitglied des globalen Objekts (das Fenster, vorausgesetzt, Sie befinden sich natürlich in einem Browser) der tatsächliche Modulwert ist. Nehmen wir an, ModulA fügt sich windowals 'modA' hinzu (genau wie jQuery und Unterstrich als $ bzw. _), dann setzen wir unseren Exportwert auf 'modA'.

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

RequireJS erhält einen lokalen Verweis auf dieses Modul. Das globale modA wird auch weiterhin auf der Seite vorhanden sein.

- Benutzerdefinierte Initialisierung für ältere "Browser Global" -Skripte

Dies ist wahrscheinlich das wichtigste Merkmal der Shim-Konfiguration, mit dem wir "Browser Global" -, "Nicht-AMD" -Skripte (die auch nicht dem modularen Muster folgen) als Abhängigkeiten in unserem eigenen Modul hinzufügen können.

Nehmen wir an, Modul B ist einfaches altes Javascript mit nur zwei Funktionen funcA () und funcB ().

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

Obwohl beide Funktionen im Fensterbereich verfügbar sind, empfiehlt RequireJS, sie über ihre globale Kennung / Handle zu verwenden, um Verwirrungen zu vermeiden. So konfigurieren Sie die Unterlegscheibe als

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

Der Rückgabewert der Init-Funktion wird anstelle des über die Zeichenfolge 'export' gefundenen Objekts als Modul-Exportwert verwendet. Dadurch können wir funcB in unserem eigenen Modul als verwenden

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

Hoffe das hat geholfen.

nalinc
quelle
3
Einfach zu verstehen! Eine Frage: Wird im letzten Beispiel die Eigenschaft "Exporte" einfach ignoriert?
Niko Bellic
Nein, es wird nicht ignoriert. Wäre die Eigenschaft "export" im letzten Beispiel ignoriert worden, wäre das Objekt, das Sie als Parameter übergeben (in diesem Fall 'B'), undefiniert, da Modul B NICHT AMD-kompatibel ist und kein Objekt für RequireJS zurückgegeben hätte ( daher würde 'B.funcB' nicht funktionieren).
Nalinc
Hmm. Ich dachte, der Wert des Exports würde von dem Objekt überschrieben, das in der Init-Funktion zurückgegeben wird. Der Parameter B wäre also das Objekt {funcA: funcA, funcB: funcB}, nicht einfach funcB für sich. Ist das nicht wahr?
Niko Bellic
4
Niko Bellic hat recht, Export wird ignoriert (das habe ich gerade getestet). Objekt B ist das Objekt, das von der im Teil 'init' angegebenen Funktion zurückgegeben wird. Wenn Sie den 'init'-Teil entfernen, wird Objekt B zur Funktion funcB, sodass Sie einfach B () anstelle von B.funcB () ausführen. Und offensichtlich würde funcA in diesem Fall unzugänglich werden.
user4205580
-2

Sie müssen Pfade in requirejs.config hinzufügen, um zu deklarieren. Beispiel:

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
quelle
1
Diese Antwort ist ein Code-Dump, der nicht erklärt, warum und wann Shim Config verwendet werden soll. Wenn Sie Ihre Antwort bearbeiten, um eine Erklärung bereitzustellen, stellen Sie sicher, dass Sie etwas Neues hinzufügen, das nicht bereits durch frühere Antworten abgedeckt ist
Louis
Kopieren Einfügen ohne positives Feedback
william.eyidi
sollte ein Komma vor Shim sein:
Scott