webentwicklung-frage-antwort-db.com.de

Node-Style benötigt Javascript im Browser?

Gibt es Bibliotheken für In-Browser-Javascript, die die gleiche Flexibilität/Modularität/Benutzerfreundlichkeit bieten wie Nodes require?

Weitere Informationen: Der Grund, warum require so gut ist, ist folgender:

  1. Ermöglicht das dynamische Laden von Code von anderen Standorten (was meiner Meinung nach stilistisch besser ist, als den gesamten Code im HTML-Code zu verknüpfen)
  2. Es bietet eine konsistente Schnittstelle zum Erstellen von Modulen
  3. Es ist einfach für Module, von anderen Modulen abhängig zu sein (also könnte ich zum Beispiel eine API schreiben, die jQuery benötigt, damit ich jQuery.ajax() verwenden kann.
  4. Geladenes Javascript ist Gültigkeitsbereich, was bedeutet, dass ich mit var dsp = require("dsp.js"); laden könnte und auf dsp.FFT zugreifen könnte, was meinen lokalen var FFT nicht beeinträchtigen würde.

Ich habe noch keine Bibliothek gefunden, die dies effektiv erledigt. Die Problemumgehungen, die ich 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 gut ist (z. B. das 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 ähnlich, dass es fehlt Scoping, obwohl ich noch nie Gelegenheit hatte, es zu verwenden. Ähnlich kann LABjs geladen werden und .wait() beseitigt Abhängigkeitsprobleme, aber es führt immer noch kein Scoping durch.)

Soweit ich das beurteilen kann, scheint es viele Lösungen für das dynamische und/oder asynchrone Laden von Javascript zu geben, aber sie neigen dazu, die gleichen Scoping-Probleme zu haben wie nur 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, es mir aber dennoch ermöglicht, Bibliotheken zu laden und zu verwenden (genau wie es der Knoten erfordert).

EDIT (MEINE ANTWORT): Seit ich dies geschrieben habe, habe ich ausführlich RequireJS verwendet (was jetzt eine viel klarere Dokumentation hat). RequireJS war meiner Meinung nach wirklich die richtige Wahl. Ich möchte klären, wie das System bei 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 definiert. Sie können Ihr Projekt auch mit r.js zu einer einzigen Datei für die Bereitstellung kompilieren (in der Praxis ist dies fast immer schneller, obwohl require Skripte parallel laden kann).

Der Hauptunterschied zwischen RequireJS und Node-Style, den browserify (ein cooles Projekt, das von tjameson vorgeschlagen wird) verwendet, besteht in der Art und Weise, wie Module entworfen und benötigt werden:

  • RequireJS verwendet AMD (Async Module Definition). In AMD verwendet require eine Liste der zu ladenden Module (Javascript-Dateien) und eine Rückruffunktion. Wenn es jedes der Module geladen hat, 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 ist require ein blockierender Aufruf, der ein Modul lädt und als Objekt zurückgibt. Dies funktioniert gut für Node, da Dateien vom 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 daher CommonJS) verwendet, bevor sie jemals AMD gesehen haben. Darüber hinaus wurden viele Bibliotheken/Module für CommonJS geschrieben (indem Dinge zu einem exports hinzugefügt wurden). Objekt) und nicht für AMD (durch Zurückgeben des Moduls von der Funktion define. Daher möchten viele Entwickler von Node-turned-Web CommonJS-Bibliotheken im Web verwenden. Dies ist möglich, da sie von einem <script> -Tag geladen werden Lösungen wie browserify nehmen CommonJS (Node) -Module und binden sie ein, damit Sie sie in Skript-Tags einbinden können.

Wenn Sie ein eigenes Projekt mit mehreren Dateien für das Web entwickeln, empfehle ich daher dringend RequireJS, da es sich wirklich um ein Modulsystem für das Web handelt (obwohl AMD meiner Meinung nach viel natürlicher ist als CommonJS). In letzter Zeit hat die Unterscheidung an Bedeutung verloren, da Sie mit RequireJS jetzt im Wesentlichen die CommonJS-Syntax verwenden können. Außerdem kann RequireJS verwendet werden, um AMD-Module in Node (obwohl ich node-AMD-loader bevorzuge) zu laden.

71
Alex Churchill

Check out ender . Es macht viel davon.

Auch browserify ist ziemlich gut. Ich habe Require-Kiss verwendet und es funktioniert. Es gibt wahrscheinlich noch andere.

Ich bin mir bei RequireJS nicht sicher. Es ist einfach nicht dasselbe wie bei einem Knoten. Möglicherweise treten beim Laden von einem anderen Speicherort Probleme auf, die jedoch möglicherweise funktionieren. Solange es eine Methode zum Bereitstellen oder etwas gibt, das aufgerufen werden kann.

TL; DR - Ich würde Browserify oder Require-Kiss empfehlen.

Update:

require-kiss ist jetzt tot und der Autor hat es entfernt. Ich benutze RequireJS seitdem ohne Probleme. Der Autor von require-kiss schrieb pakmanager und pakman . Vollständige Offenlegung, ich arbeite mit dem Entwickler.

Persönlich mag ich RequireJS besser. Es ist viel einfacher zu debuggen (Sie können separate Dateien in der Entwicklung und eine einzelne bereitgestellte Datei in der Produktion haben) und basiert auf einem soliden "Standard".

15
beatgammit

Ich habe ein kleines Skript geschrieben, das das asynchrone und synchrone Laden von Javascript-Dateien ermöglicht, was hier von Nutzen sein könnte. Es hat keine Abhängigkeiten und ist kompatibel zu Node.js & CommonJS. Sie können sogar mehrere Module in einer Datei bündeln, um HTTP-Anforderungen auf Produktionsservern zu reduzieren. Die Benutzung ist ziemlich einfach:

<script type="text/javascript" src="require.js"></script>
<script type="text/javascript">
    var ModuleA = require('modulea') // Sync loading of a script in the module directory
    ModuleA.funcA();

    require('./path/moduleb.js', callbackB); // Async loading of a script anywhere else
    function callbackB(ModuleB) {
        ModuleB.funcB();
    }
</script>

Weitere Details und den Code finden Sie in meinem Blog: http://pixelsvsbytes.com/2013/02/js-require-for-browsers-better-faster-stronger/ Der Code ist auch aktiviert GitHub: https://github.com/letorbi/tarp.require

13
Torben

Eine Variation von Ilya Kharlamov großartige Antwort , mit etwas Code, damit es mit chrome developer tools) Nizza spielt.

//
///- REQUIRE FN
// equivalent to require from node.js
function require(url){
    if (url.toLowerCase().substr(-3)!=='.js') url+='.js'; // to allow loading without js suffix;
    if (!require.cache) require.cache=[]; //init cache
    var exports=require.cache[url]; //get from cache
    if (!exports) { //not cached
            try {
                exports={};
                var X=new XMLHttpRequest();
                X.open("GET", url, 0); // sync
                X.send();
                if (X.status && X.status !== 200)  throw new Error(X.statusText);
                var source = X.responseText;
                // fix (if saved form for Chrome Dev Tools)
                if (source.substr(0,10)==="(function("){ 
                    var moduleStart = source.indexOf('{');
                    var moduleEnd = source.lastIndexOf('})');
                    var CDTcomment = source.indexOf('//@ ');
                    if (CDTcomment>-1 && CDTcomment<moduleStart+6) moduleStart = source.indexOf('\n',CDTcomment);
                    source = source.slice(moduleStart+1,moduleEnd-1); 
                } 
                // fix, add comment to show source on Chrome Dev Tools
                source="//@ sourceURL="+window.location.Origin+url+"\n" + source;
                //------
                var module = { id: url, uri: url, exports:exports }; //according to node.js modules 
                var anonFn = new Function("require", "exports", "module", source); //create a Fn with module code, and 3 params: require, exports & module
                anonFn(require, exports, module); // call the Fn, Execute the module
                require.cache[url]  = exports = module.exports; //cache obj exported by module
            } catch (err) {
                throw new Error("Error loading module "+url+": "+err);
            }
    }
    return exports; //require returns object exported by module
}
///- END REQUIRE FN
7
Lucio M. Tato
(function () {
    // c is cache, the rest are the constants
    var c = {},s="status",t="Text",e="exports",E="Error",r="require",m="module",S=" ",w=window;
    w[r]=function R(url) {
        url+=/.js$/i.test(url) ? "" : ".js";// to allow loading without js suffix;
        var X=new XMLHttpRequest(),module = { id: url, uri: url }; //according to the modules 1.1 standard
        if (!c[url])
            try {
                X.open("GET", url, 0); // sync
                X.send();
                if (X[s] && X[s] != 200) 
                    throw X[s+t];
                Function(r, e, m, X['response'+t])(R, c[url]={}, module); // Execute the module
                module[e] && (c[url]=module[e]);
            } catch (x) {
                throw w[E](E+" in "+r+": Can't load "+m+S+url+":"+S+x);
            }
        return c[url];
    }
})();

Besser wegen der Blockierung nicht in der Produktion verwenden. (In node.js ist require () ein blockierender Aufruf gut).

5
Ilya Kharlamov

Require-stub - Stellt im Browser knotenkompatibles require bereit und löst sowohl Module als auch relative Pfade auf. Verwendet eine ähnliche Technik wie TKRequire (XMLHttpRequest). Der resultierende Code ist vollständig browserfähig, da require-stub kann als Ersatz für watchify dienen.

1
dy_

Webmake bündelt Module im Node-Stil für den Browser, probieren Sie es aus.

1
Mariusz Nowak

Hier ist eine Erweiterung der fantastischen Antwort von Lucio M. Tato, die das rekursive Laden von Modulen mit relativen Pfaden ermöglicht.

Hier ist ein Github-Projekt zur Unterbringung der Lösung und ein Beispiel für deren Verwendung:

https://github.com/trausti/TKRequire.js

Um TKRequire.js zu verwenden, fügen Sie die folgende Zeile in Ihre Kopfzeile ein

<script type = "text/javascript" src = "./ TKRequire.js"> </ script>

Dann laden Sie Module wie in node.js:

var MyModule = require ("./ relative/path/to/MyModule.js");