Was ist der Unterschied zwischen der Verwendung von Require.JS und dem einfachen Erstellen eines <script>
Elements im DOM?
Mein Verständnis von Require.JS ist, dass es die Möglichkeit bietet, Abhängigkeiten zu laden, aber dies kann nicht einfach durch Erstellen eines <script>
Elements erfolgen, das die erforderliche externe JS-Datei lädt?
Nehmen wir zum Beispiel an, ich habe die Funktion doStuff()
, für die die Funktion erforderlich ist needMe()
. doStuff()
befindet sich in der externen Datei do_stuff.js
, während needMe()
es sich in der externen Datei befindet need_me.js
.
Tun Sie dies auf die Require.JS-Weise:
define(['need_me'],function(){
function doStuff(){
//do some stuff
needMe();
//do some more stuff
}
});
Dazu erstellen Sie einfach ein Skriptelement:
function doStuff(){
var scriptElement = document.createElement('script');
scriptElement.src = 'need_me.js';
scriptElement.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(scriptElement);
//do some stuff
needMe();
//do some more stuff
}
Beide arbeiten. In der zweiten Version muss ich jedoch nicht die gesamte Require.js-Bibliothek laden. Ich sehe keinen funktionalen Unterschied ...
quelle
Antworten:
Hier ist der schöne Artikel auf ajaxian.com, warum man es benutzt:
RequireJS: Asynchrones Laden von JavaScript
quelle
In Ihrem Beispiel erstellen Sie das Skript-Tag asynchron, was bedeutet, dass Ihre
needMe()
Funktion zuvor aufgerufen wurde Dies die Datei need_me.js vollständig geladen wird. Dies führt zu nicht erfassten Ausnahmen, bei denen Ihre Funktion nicht definiert ist.Stattdessen müssen Sie Folgendes tun, damit das, was Sie vorschlagen, tatsächlich funktioniert:
Möglicherweise ist es am besten, einen Paketmanager wie RequireJS zu verwenden oder eine reine JavaScript-Strategie zu verwenden, wie oben gezeigt. Während Ihre Webanwendung möglicherweise schneller geladen wird, ist das Aufrufen von Funktionen und Features auf der Site langsamer, da auf das Laden von Ressourcen gewartet werden muss, bevor diese Aktion ausgeführt werden kann.
Wenn eine Webanwendung als einseitige App erstellt wird, sollten Sie berücksichtigen, dass die Benutzer die Seite nicht sehr oft neu laden. In diesen Fällen würde das Vorladen von allem dazu beitragen, dass die Erfahrung bei der tatsächlichen Verwendung schneller erscheint der App . In diesen Fällen haben Sie Recht, Sie können lediglich alle Ressourcen laden, indem Sie einfach die Skript-Tags in den Kopf oder den Hauptteil der Seite einfügen.
Wenn Sie jedoch eine Website oder eine Webanwendung erstellen, die dem traditionelleren Modell folgt, bei dem von Seite zu Seite gewechselt wird, wodurch Ressourcen neu geladen werden, kann ein Ansatz zum verzögerten Laden dazu beitragen, diese Übergänge zu beschleunigen.
quelle
Einige andere sehr wichtige Gründe, warum die Verwendung von RequireJS sinnvoll ist:
Entnommen aus den Kommentaren von rmurphey hier in diesem Gist .
Abstraktionsebenen können ein Albtraum sein, an den man lernen und sich anpassen kann, aber wenn sie einen Zweck erfüllen und es gut machen, macht es einfach Sinn.
quelle
Hier ist ein konkreteres Beispiel.
Ich arbeite in einem Projekt mit 60 Dateien. Wir haben 2 verschiedene Modi, um es auszuführen.
Laden Sie eine verkettete Version, 1 große Datei. (Produktion)
Laden Sie alle 60 Dateien (Entwicklung)
Wir verwenden einen Loader, sodass wir nur ein Skript auf der Webseite haben
Der Standardwert ist Modus 1 (Laden der einen großen verketteten Datei). Um den In-Modus Nr. 2 (separate Dateien) auszuführen, setzen wir ein Flag. Es könnte alles sein. Ein Schlüssel in der Abfragezeichenfolge. In diesem Beispiel machen wir das einfach
loader.js sieht ungefähr so aus
Das Build-Skript ist nur eine .sh-Datei, die so aussieht
etc...
Wenn eine neue Datei hinzugefügt wird, verwenden wir wahrscheinlich Modus 2, da wir die Entwicklung durchführen, müssen wir eine hinzufügen
injectScript("somenewfile.js")
loader.js Zeile hinzufügenSpäter für die Produktion müssen wir dann auch somenewfile.js zu unserem Build-Skript hinzufügen. Ein Schritt, den wir oft vergessen und dann Fehlermeldungen erhalten.
Durch den Wechsel zu AMD müssen nicht 2 Dateien bearbeitet werden. Das Problem, loader.js und das Build-Skript synchron zu halten, verschwindet. Verwenden von
r.js
oderwebpack
es kann nur den zu erstellenden Code lesenlarge-concantinated.js
Es kann auch mit Abhängigkeiten umgehen, zum Beispiel hatten wir 2 Dateien lib1.js und lib2.js so geladen
lib2 braucht lib1. Es enthält Code, der so etwas wie tut
Da die injizierten Skripte jedoch asynchron geladen werden, gibt es keine Garantie dafür, dass sie in der richtigen Reihenfolge geladen werden. Diese beiden Skripte sind keine AMD-Skripte, aber mit require.js können wir ihre Abhängigkeiten erkennen
In unserem Modul, das lib1 verwendet, machen wir das
Jetzt wird require.js die Skripte für uns injizieren und lib2 erst injizieren, wenn lib1 geladen wurde, da wir gesagt haben, dass lib2 von lib1 abhängt. Es wird auch unser Modul, das lib1 verwendet, erst gestartet, wenn sowohl lib2 als auch lib1 geladen wurden.
Dies macht die Entwicklung angenehm (kein Build-Schritt, keine Sorge um die Ladereihenfolge) und die Produktion (keine Notwendigkeit, ein Build-Skript für jedes hinzugefügte Skript zu aktualisieren).
Als zusätzlichen Bonus können wir das Babel-Plugin von Webpack verwenden, um Babel über den Code für ältere Browser auszuführen, und auch dieses Build-Skript müssen wir nicht warten.
Beachten Sie, dass wenn Chrome (unser Browser der Wahl) anfangen würde,
import
wirklich zu unterstützen, wir wahrscheinlich für die Entwicklung zu diesem wechseln würden, aber das würde nichts wirklich ändern. Wir könnten weiterhin Webpack verwenden, um eine verkettete Datei zu erstellen, und wir könnten es verwenden, um Babel über den Code für alle Browser auszuführen.All dies wird dadurch erreicht, dass keine Skript-Tags und AMD verwendet werden
quelle