Gibt es Bibliotheken für In-Browser-Javascript, die die gleiche Flexibilität / Modularität / Benutzerfreundlichkeit bieten wie die von Node require
?
Um mehr Details zu liefern: Der Grund require
ist so gut, dass es:
- Ermöglicht das dynamische Laden von Code von anderen Speicherorten (was meiner Meinung nach stilistisch besser ist, als den gesamten Code im HTML zu verknüpfen).
- Es bietet eine konsistente Schnittstelle zum Erstellen von Modulen
- Es ist für Module einfach, von anderen Modulen abhängig zu sein (so könnte ich beispielsweise eine API schreiben, für die jQuery erforderlich ist, damit ich sie verwenden kann
jQuery.ajax()
- Geladenes Javascript hat einen Gültigkeitsbereich , was bedeutet , dass ich es laden
var dsp = require("dsp.js");
und darauf zugreifen kanndsp.FFT
, was meine lokale Umgebung nicht beeinträchtigen würdevar FFT
Ich habe noch keine Bibliothek gefunden, die dies effektiv erledigt. Die Problemumgehungen, die ich normalerweise verwende, sind:
coffeescript-concat - es ist einfach genug, andere js zu benötigen, aber Sie müssen es kompilieren, was bedeutet, dass es für eine schnelle Entwicklung weniger geeignet ist (z. B. Erstellen von APIs im Test)
RequireJS - Es ist beliebt, unkompliziert und löst 1-3, aber mangelndes Scoping ist ein echter Deal-Breaker (ich glaube, head.js ist insofern ähnlich, als es kein Scoping gibt, obwohl ich nie Gelegenheit hatte, es zu verwenden. In ähnlicher Weise können LABjs
.wait()
Abhängigkeitsprobleme laden und besänftigen , aber es wird immer noch kein Scoping durchgeführt.
Soweit ich das beurteilen kann, scheint es viele Lösungen für das dynamische und / oder asynchrone Laden von Javascript zu geben, aber sie haben tendenziell die gleichen Probleme wie das Laden der Js aus HTML. Vor allem möchte ich eine Möglichkeit zum Laden von Javascript, die den globalen Namespace überhaupt nicht verschmutzt, mir aber dennoch das Laden und Verwenden von Bibliotheken ermöglicht (genau wie es der Knoten erfordert).
2020 UPDATE: Module sind jetzt Standard in ES6 und werden ab Mitte 2020 von den meisten Browsern nativ unterstützt . Module unterstützen sowohl das synchrone als auch das asynchrone Laden (mit Promise). Meine aktuelle Empfehlung lautet, dass die meisten neuen Projekte ES6-Module verwenden und einen Transpiler verwenden sollten, um für ältere Browser auf eine einzelne JS-Datei zurückzugreifen.
Generell ist die Bandbreite heute auch viel größer als damals, als ich diese Frage gestellt habe. In der Praxis könnten Sie sich also vernünftigerweise dafür entscheiden, immer einen Transpiler mit ES6-Modulen zu verwenden und sich eher auf die Code-Effizienz als auf das Netzwerk zu konzentrieren.
VORHERIGE BEARBEITUNG (oder wenn Sie ES6-Module nicht mögen): Seit dem Schreiben habe ich RequireJS (das jetzt eine viel klarere Dokumentation enthält) ausgiebig verwendet . RequireJS war meiner Meinung nach wirklich die richtige Wahl. Ich möchte klarstellen, wie das System für Menschen funktioniert, die genauso verwirrt sind wie ich:
Sie können require
in der täglichen Entwicklung verwenden. Ein Modul kann alles sein, was von einer Funktion zurückgegeben wird (normalerweise ein Objekt oder eine Funktion) und wird als Parameter festgelegt. Sie können Ihr Projekt auch zur Bereitstellung in eine einzige Datei kompilieren r.js
(in der Praxis ist dies fast immer schneller, obwohl require
Skripte parallel geladen werden können).
Der Hauptunterschied zwischen RequireJS und Node-Style-Anforderungen wie browserify (ein cooles Projekt, das von tjameson vorgeschlagen wird) besteht in der Art und Weise, wie Module entworfen und benötigt werden:
- RequireJS verwendet AMD (Async Module Definition). In AMD werden
require
eine Liste der zu ladenden Module (Javascript-Dateien) und eine Rückruffunktion verwendet. Wenn jedes der Module geladen wurde, ruft es den Rückruf mit jedem Modul als Parameter für den Rückruf auf. Somit ist es wirklich asynchron und daher gut für das Web geeignet. - Der Knoten verwendet CommonJS. In CommonJS
require
handelt es sich um einen blockierenden Aufruf, der ein Modul lädt und als Objekt zurückgibt. Dies funktioniert gut für Node, da Dateien aus dem Dateisystem gelesen werden, was schnell genug ist, aber im Web schlecht funktioniert, da das synchrone Laden von Dateien viel länger dauern kann.
In der Praxis haben viele Entwickler Node (und damit CommonJS) verwendet, bevor sie AMD jemals sehen. Darüber hinaus werden viele Bibliotheken / Module für CommonJS (durch Hinzufügen von Elementen zu einem exports
Objekt) und nicht für AMD (durch Zurückgeben des Moduls von der define
Funktion) geschrieben. Daher möchten viele Node-Turned-Web-Entwickler CommonJS-Bibliotheken im Web verwenden. Dies ist möglich, da das Laden von einem <script>
Tag blockiert. Lösungen wie browserify verwenden CommonJS (Node) -Module und schließen sie zusammen, damit Sie sie in Skript-Tags einfügen können.
Wenn Sie Ihr eigenes Projekt mit mehreren Dateien für das Web entwickeln, empfehle ich RequireJS dringend, da es sich wirklich um ein Modulsystem für das Web handelt (obwohl ich AMD bei fairer Offenlegung viel natürlicher finde als CommonJS). In letzter Zeit hat die Unterscheidung an Bedeutung verloren, da Sie mit RequireJS jetzt im Wesentlichen die CommonJS-Syntax verwenden können. Zusätzlich kann RequireJS verwendet werden, um AMD-Module in Node zu laden (obwohl ich Node-Amd-Loader bevorzuge ).