Ich erstelle eine kleine Anwendung mit einem JavaScript-Client (im Browser ausgeführt) und einem Node.js-Server, der über WebSocket kommuniziert.
Ich möchte Code zwischen dem Client und dem Server teilen. Ich habe gerade erst mit Node.js angefangen und meine Kenntnisse über modernes JavaScript sind, gelinde gesagt, etwas verrostet. Ich beschäftige mich also immer noch mit der CommonJS require () -Funktion. Wenn ich meine Pakete mit dem Objekt 'export' erstelle, kann ich nicht sehen, wie ich dieselben JavaScript-Dateien im Browser verwenden kann.
Ich möchte eine Reihe von Methoden und Klassen erstellen, die an beiden Enden verwendet werden, um das Codieren und Decodieren von Nachrichten und andere gespiegelte Aufgaben zu erleichtern. Die Node.js / CommonJS-Verpackungssysteme scheinen mich jedoch daran zu hindern, JavaScript-Dateien zu erstellen, die auf beiden Seiten verwendet werden können.
Ich habe auch versucht, mit JS.Class ein engeres OO-Modell zu erhalten, aber ich habe aufgegeben, weil ich nicht herausfinden konnte, wie die bereitgestellten JavaScript-Dateien mit require () funktionieren. Fehlt mir hier etwas?
quelle
Antworten:
Wenn Sie ein Modul schreiben möchten, das sowohl clientseitig als auch serverseitig verwendet werden kann, habe ich einen kurzen Blogbeitrag über eine schnelle und einfache Methode: Schreiben für Node.js und den Browser , im Wesentlichen das Folgende (wo
this
ist dasselbe wiewindow
) ::Alternativ gibt es einige Projekte, die darauf abzielen, die Node.js-API auf der Clientseite zu implementieren, z. B. Maraks Zwillinge .
Möglicherweise interessiert Sie auch DNode , mit dem Sie eine JavaScript-Funktion verfügbar machen können , damit sie mithilfe eines einfachen JSON-basierten Netzwerkprotokolls von einem anderen Computer aus aufgerufen werden kann.
quelle
Epeli hat hier eine nette Lösung http://epeli.github.com/piler/ , die sogar ohne die Bibliothek funktioniert. Fügen Sie diese einfach in eine Datei namens share.js ein
Auf der Serverseite verwenden Sie einfach:
Und auf der Clientseite laden Sie einfach die js-Datei und verwenden Sie sie dann
quelle
Überprüfen Sie den jQuery-Quellcode, mit dem dies funktioniert, im Node.js-Modulmuster, im AMD-Modulmuster und global im Browser:
quelle
Vergessen Sie nicht, dass die Zeichenfolgendarstellung einer JavaScript-Funktion den Quellcode für diese Funktion darstellt. Sie können Ihre Funktionen und Konstruktoren einfach gekapselt schreiben, damit sie toString () 'd sind und an den Client gesendet werden.
Eine andere Möglichkeit besteht darin, ein Build-System zu verwenden, den gemeinsamen Code in separaten Dateien abzulegen und diese dann sowohl in die Server- als auch in die Client-Skripte aufzunehmen. Ich verwende diesen Ansatz für ein einfaches Client / Server-Spiel über WebSockets, bei dem sowohl Server als auch Client im Wesentlichen dieselbe Spielschleife ausführen und der Client bei jedem Tick mit dem Server synchronisiert, um sicherzustellen, dass niemand betrügt.
Mein Build-System für das Spiel ist ein einfaches Bash- Skript, das die Dateien über den C-Präprozessor und dann über sed ausführt, um einige zurückgelassene Junk-CPP-Blätter zu bereinigen, sodass ich alle normalen Präprozessor-Inhalte wie #include, #define, #ifdef verwenden kann , etc.
quelle
Ich würde empfehlen, in den RequireJS-Adapter für Node.js zu schauen . Das Problem ist, dass das von Node.js standardmäßig verwendete CommonJS-Modulmuster nicht asynchron ist, wodurch das Laden im Webbrowser blockiert wird. RequireJS verwendet das AMD-Muster, das sowohl asynchron als auch mit Server und Client kompatibel ist, solange Sie den
r.js
Adapter verwenden.quelle
Vielleicht stimmt das nicht ganz mit der Frage überein, aber ich dachte, ich würde das teilen.
Ich wollte ein paar einfache Funktionen des String-Dienstprogramms, die in String.prototype deklariert sind, sowohl für den Knoten als auch für den Browser verfügbar machen. Ich behalte diese Funktionen einfach in einer Datei namens utilities.js (in einem Unterordner) und kann sie sowohl über ein Skript-Tag in meinem Browser-Code als auch mithilfe von require (ohne die Erweiterung .js) in meinem Node.js-Skript referenzieren ::
my_node_script.js
my_browser_code.html
Ich hoffe, dies sind nützliche Informationen für andere als mich.
quelle
utilites.js
mit einer einzelnen Zeilemodule.exports = require('./static/js/utilities');
. Auf diese Weise müssen Sie nur einen Pfad aktualisieren, wenn Sie Inhalte mischen.utilities.js
befindet sich imshared
Ordner unter dem Projekt. Die Verwendungrequire('/shared/utilities')
gab mir den FehlerCannot find module '/shared/utilities'
. Ich muss so etwas verwendenrequire('./../../shared/utilities')
, damit es funktioniert. Es geht also immer vom aktuellen Ordner und wandert nach oben zum Stamm und dann nach unten.Wenn Sie Modulbündler wie Webpack verwenden, um JavaScript-Dateien für die Verwendung in einem Browser zu bündeln, können Sie Ihr Node.js-Modul einfach für das in einem Browser ausgeführte Frontend wiederverwenden. Mit anderen Worten, Ihr Node.js-Modul kann von Node.js und dem Browser gemeinsam genutzt werden.
Sie haben beispielsweise den folgenden Code sum.js:
Normales Node.js-Modul: sum.js
Verwenden Sie das Modul in Node.js.
Verwenden Sie es im Frontend wieder
quelle
Der Server kann einfach JavaScript-Quelldateien an den Client (Browser) senden. Der Trick besteht jedoch darin, dass der Client eine Mini-Exportumgebung bereitstellen muss, bevor er
exec
den Code erstellen und als Modul speichern kann.Eine einfache Möglichkeit, eine solche Umgebung zu erstellen, ist die Verwendung eines Verschlusses. Angenommen, Ihr Server stellt Quelldateien wie HTTP bereit
http://example.com/js/foo.js
. Der Browser kann die erforderlichen Dateien über eine XMLHttpRequest laden und den Code wie folgt laden:Der Schlüssel ist, dass der Client den Fremdcode in eine anonyme Funktion einbinden kann, die sofort ausgeführt wird (ein Abschluss), wodurch das Objekt "exportiert" erstellt und zurückgegeben wird, sodass Sie es an der gewünschten Stelle zuweisen können, anstatt den globalen Namespace zu verschmutzen. In diesem Beispiel wird es dem Fensterattribut zugewiesen, das
fooModule
den von der Datei exportierten Code enthältfoo.js
.quelle
window.fooModule = {}; (new Function('exports', xhr.responseText))(window.fooModule)
.Keine der vorherigen Lösungen bringt das CommonJS-Modulsystem in den Browser.
Wie in den anderen Antworten erwähnt, gibt es Asset Manager / Packager-Lösungen wie Browserify oder Piler und RPC-Lösungen wie dnode oder nowjs .
Ich konnte jedoch keine Implementierung von CommonJS für den Browser finden (einschließlich einer
require()
Funktion undexports
/ oder vonmodule.exports
Objekten usw.). Also schrieb ich mein eigenes, um später festzustellen, dass jemand anderes es besser geschrieben hatte als ich: https://github.com/weepy/brequire . Es heißt Brequire (kurz für Browser erforderlich).Gemessen an der Popularität entsprechen die Vermögensverwalter den Anforderungen der meisten Entwickler. Wenn Sie jedoch eine Browser-Implementierung von CommonJS benötigen, ist Brequire wahrscheinlich genau das Richtige für Sie.
Update 2015: Ich verwende Brequire nicht mehr (es wurde seit einigen Jahren nicht mehr aktualisiert). Wenn ich nur ein kleines Open-Source-Modul schreibe und möchte, dass jeder es einfach verwenden kann, dann folge ich einem ähnlichen Muster wie Caolans Antwort (oben) - ich habe ein paar Jahre lang einen Blog-Beitrag darüber geschrieben vor.
Wenn ich jedoch Module für den privaten Gebrauch oder für eine Community schreibe, die auf CommonJS standardisiert ist (wie die Ampersand- Community), schreibe ich sie einfach im CommonJS-Format und verwende Browserify .
quelle
now.js ist auch einen Blick wert. Sie können serverseitig von der Clientseite und clientseitige Funktionen von der Serverseite aus aufrufen
quelle
Wenn Sie Ihren Browser im Node.js-ähnlichen Stil schreiben möchten, können Sie Dualify ausprobieren .
Es gibt keine Browser-Code-Kompilierung, sodass Sie Ihre Anwendung ohne Einschränkungen schreiben können.
quelle
Schreiben Sie Ihren Code als RequireJS- Module und Ihre Tests als Jasmine- Tests.
Auf diese Weise kann Code überall mit RequireJS geladen werden und die Tests werden im Browser mit jasmine-html und mit jasmine-node in Node.js ausgeführt, ohne dass der Code oder die Tests geändert werden müssen.
Hier ist ein funktionierendes Beispiel dafür.
quelle
Anwendungsfall: Teilen Sie Ihre App-Konfiguration zwischen Node.js und dem Browser (dies ist nur eine Illustration, wahrscheinlich nicht der beste Ansatz, abhängig von Ihrer App).
Problem: Sie können weder
window
(existiert nicht in Node.js) nochglobal
(existiert nicht im Browser) verwenden.Lösung:
Datei config.js:
Im Browser (index.html):
Sie können jetzt die Entwicklungswerkzeuge öffnen und auf die globale Variable zugreifen
config
In Node.js (app.js):
Mit Babel oder TypeScript:
quelle
shared.js
undhelpers.js
-shared.js
verwendet Funktionen vonhelpers.js
, sodass sie oben benötigt werden, damit sieconst { helperFunc } = require('./helpers')
serverseitig funktionieren. Das Problem liegt auf dem Client, es beschwert sich darüber, dass esrequire
keine Funktion ist, aber wenn ich die erforderliche Zeileif (typeof module === 'object') { ... }
einbinde, sagt der Server, dass helperFunc () nicht definiert ist (außerhalb der if-Anweisung). Irgendwelche Ideen, um es auf beiden zum Laufen zu bringen?shared.js
:helperFunc = (typeof exports === 'undefined') ? helperFunc : require('./helpers').helperFunc;
- Benötige ich leider eine Zeile für jede exportierte Funktion, aber hoffentlich ist es eine gute Lösung?Ich habe ein einfaches Modul geschrieben , das importiert werden kann (entweder mit require in Node oder mit Skript-Tags im Browser), mit dem Sie Module sowohl vom Client als auch vom Server laden können.
Anwendungsbeispiel
1. Modul definieren
Platzieren Sie Folgendes in einer Datei
log2.js
in Ihrem statischen Ordner für Webdateien:So einfach ist das!
2. Verwenden des Moduls
Da es sich um einen bilateralen Modullader handelt, können wir ihn von beiden Seiten (Client und Server) laden. Daher können Sie Folgendes tun, müssen jedoch nicht beide gleichzeitig ausführen (geschweige denn in einer bestimmten Reihenfolge):
In Node ist es einfach:
Dies sollte zurückkehren
2
.Wenn sich Ihre Datei nicht im aktuellen Verzeichnis von Node befindet, stellen Sie sicher, dass Sie
loader.setRoot
den Pfad zu Ihrem statischen Ordner für Webdateien (oder wo immer sich Ihr Modul befindet) aufrufen .Definieren Sie zunächst die Webseite:
Stellen Sie sicher , dass Sie nicht die Datei direkt in Ihrem Browser öffnen; Da AJAX verwendet wird, sollten Sie sich stattdessen das Python 3-
http.server
Modul ansehen (oder was auch immer Ihre superschnelle, Befehlszeilen- und Ordner-Webserver-Bereitstellungslösung ist).Wenn alles gut geht, erscheint Folgendes:
quelle
Ich habe dies geschrieben, es ist einfach zu verwenden, wenn Sie alle Variablen auf den globalen Bereich setzen möchten:
quelle