Was ist der Unterschied zwischen Require.js und dem einfachen Erstellen eines <script> -Elements im DOM? [geschlossen]

138

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 ...

Maxedison
quelle
1
Was ist mit dem Zwischenspeichern von Browsern?
Muhammad Umer
Ich öffne das wieder, weil es nach dem Unterschied zwischen zwei sehr ähnlichen Dingen fragt. Es kann objektiv beantwortet werden, und ich sehe nicht, wo die Meinung dazu passt.
RamenChef

Antworten:

43

Hier ist der schöne Artikel auf ajaxian.com, warum man es benutzt:

RequireJS: Asynchrones Laden von JavaScript

  • eine Art # include / import / require
  • Fähigkeit, verschachtelte Abhängigkeiten zu laden
  • Benutzerfreundlichkeit für Entwickler, aber unterstützt durch ein Optimierungstool, das die Bereitstellung unterstützt
Sarfraz
quelle
2
Ich hatte diese gelesen, aber jetzt, wo ich mehr darüber nachdenke, wird mir klar, dass die Idee verschachtelter Abhängigkeiten nicht durch einfaches Schreiben von <script> -Tags erreicht werden kann. Vielen Dank.
Maxedison
37
"Benutzerfreundlichkeit für Entwickler" könnte nicht weiter von der Wahrheit entfernt sein. Es hat definitiv eine steile Lernkurve für Sie und alle anderen, die in diesem Projekt arbeiten werden.
Sahat Yalkabov
3
@TwilightPony Ich halte mich nicht für so hell und Requirejs war nicht wirklich schwer für mich zu bekommen. Sie müssen sich keine Gedanken mehr über Abhängigkeiten machen und beschleunigen die Seite. Ihr Code passt besser zur serverseitigen Programmierung, wenn Sie Ihre Abhängigkeiten deklarieren, was ich persönlich erfrischend und einfach finde. Die Syntax war minimal und wurde vom Design her geschlossen. Anschließend wird die Roadmap für die Produktion festgelegt, um Ihre Skripte einfach zu kombinieren. Darüber hinaus ist das Debuggen wie statische Deklarationen. Ich bin mir nicht sicher, was einfacher ist. Viel schwieriger in die andere Richtung als in die andere Richtung.
Jason Sebring
Ich kämpfe. Besonders bei Modulen, die versuchen, sich an globale Objekte anzuhängen. (Module
reagieren
1
Die Kommentare auf dieser Seite ließen mich tatsächlich das Gefühl haben, dass man weglaufen sollte und nicht in Richtung erfordern. Besonders die am unteren Rand, die auf stevesouders.com/tests/require.php verweist
Dave Kanter
52

Welche Vorteile bietet Require.JS im Vergleich zum einfachen Erstellen eines Elements im DOM?

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:

function doStuff(){
    var scriptElement  = document.createElement('script');
    scriptElement.src = 'need_me.js';
    scriptElement.type = 'text/javascript';

    scriptElement.addEventListener("load", 
        function() { 
            console.log("script loaded - now it's safe to use it!");

            // do some stuff
            needMe();
            //do some more stuff

        }, false);

    document.getElementsByTagName('head')[0].appendChild(scriptElement);

}

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.

jmort253
quelle
10

Einige andere sehr wichtige Gründe, warum die Verwendung von RequireJS sinnvoll ist:

  1. Das Verwalten eigener Abhängigkeiten fällt bei umfangreichen Projekten schnell auseinander.
  2. Sie können so viele kleine Dateien haben, wie Sie möchten, und müssen sich nicht darum kümmern, Abhängigkeiten oder Ladereihenfolgen im Auge zu behalten.
  3. RequireJS ermöglicht das Schreiben einer vollständigen, modularen App, ohne das Fensterobjekt zu berühren.

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.

girls_can_code_too
quelle
9
Sie müssen weiterhin alle erforderlichen Anweisungen verwalten und Anweisungen, Konfigurationsdateien, Kollisionen mit anderen Systemen und Bibliotheken definieren, die die AMD-Spezifikation nicht implementiert haben usw. Ich habe versucht, Require.JS in einem Node-Webkit-Projekt und Require.JS zu verwenden hat mich auf jedem Schritt des Weges bekämpft ... Vergleichen Sie das damit, dass Sie Skripte einfach auf eine bestimmte Art und Weise bestellen ... Natürlich werden Sie mit Require.JS faul, weshalb ich versucht habe, es zum Laufen zu bringen. :)
jmort253
Ich stimme @ jmort253 voll und ganz zu, es war am Anfang ein Kampf, aber jetzt gefällt es mir sehr gut. Alle drei Punkte sind richtig! Und das Ändern einer Bibliothek sollte nicht so schwierig sein ... oder die Unterlegscheibe verwenden.
Legenden
0

Hier ist ein konkreteres Beispiel.

Ich arbeite in einem Projekt mit 60 Dateien. Wir haben 2 verschiedene Modi, um es auszuführen.

  1. Laden Sie eine verkettete Version, 1 große Datei. (Produktion)

  2. Laden Sie alle 60 Dateien (Entwicklung)

Wir verwenden einen Loader, sodass wir nur ein Skript auf der Webseite haben

<script src="loader.js"></script>

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

<script>useDebugVersion = true;</script>
<script src="loader.js"></script>

loader.js sieht ungefähr so ​​aus

if (useDebugVersion) {
   injectScript("app.js");
   injectScript("somelib.js");
   injectScript("someotherlib.js");
   injectScript("anotherlib.js");
   ... repeat for 60 files ...
} else {
   injectScript("large-concatinated.js");
}

Das Build-Skript ist nur eine .sh-Datei, die so aussieht

cat > large-concantinated.js app.js somelib.js someotherlib.js anotherlib.js

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ügen

Spä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.jsoderwebpack 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

injectScript("lib1.js");
injectScript("lib2.js");

lib2 braucht lib1. Es enthält Code, der so etwas wie tut

lib1Api.installPlugin(...);

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

require.config({
    paths: {
        lib1: './path/to/lib1',
        lib2: './path/to/lib2',
    },
    shim: {
        lib1: {
            "exports": 'lib1Api',
        },
        lib2: {
            "deps": ["lib1"],
        },
    }
});

In unserem Modul, das lib1 verwendet, machen wir das

define(['lib1'], function(lib1Api) {
   lib1Api.doSomething(...);
});

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, importwirklich 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

gman
quelle