Node.js Tutorial: Beginnen Sie mit Node.js

Node.js, eine plattformübergreifende JavaScript-Laufzeitumgebung für Server und Anwendungen, bietet viele Vorteile. Geringe Speichernutzung, gute Leistung und ein großes Ökosystem von Paketen, die derzeit etwa 475.000 umfassen, haben Node.js zu einer beliebten Wahl für den Aufbau von Webservern, REST-APIs, Echtzeit-Netzwerkanwendungen (z. B. Chat, Spiele) und sogar gemacht plattformübergreifende Desktop-Apps.

Wenn Sie noch nicht mit Node.js begonnen haben, ist es vielleicht an der Zeit. Schauen Sie sich meinen Node.js-Erklärer an, um zu erfahren, wie Node.js seine Magie entfaltet. In diesem Artikel werden wir Node.js und den NPM-Paketmanager installieren, einen einfachen Webserver hochfahren und das Node.js-Clustermodul verwenden, um mehrere CPU-Kerne zu nutzen.

Wir werden uns auch mit der Installation zusätzlicher Node.js-Module und anderer JavaScript-Pakete mithilfe des NPM-Paketmanagers befassen. Und wir werden ein Node.js-Framework verwenden, in diesem Fall Koa, um funktionsreichere und flexiblere Node.js-Server zu erstellen.  

Lass uns anfangen.

So installieren Sie Node.js und NPM

Beginnen Sie mit dem Navigieren zu //nodejs.org:

Node.js Foundation

Klicken Sie auf die Schaltfläche für den LTS-Download (Langzeitunterstützung), es sei denn, Sie wissen, dass Sie in der aktuellen Version eine neue Funktion benötigen. Wie genau das heruntergeladene Installationsprogramm aussehen wird, kann von Betriebssystem zu Betriebssystem unterschiedlich sein, aber auf einem Mac sieht es am Anfang folgendermaßen aus:

Sobald die Installation abgeschlossen ist, sieht es folgendermaßen aus:

Jetzt sollten Sie sicherstellen, dass sowohl Node.js als auch NPM ordnungsgemäß installiert sind. Öffnen Sie eine Befehlszeilen-Shell (Terminal auf einem Mac; Eingabeaufforderung unter Windows) und überprüfen Sie die installierten Versionen von beiden:

$ node - Version

v6.11.3

$ npm - Version

3.10.10

Wenn Sie Fehler erhalten, die besagen, dass Node.js oder NPM nicht gefunden wurden, starten Sie Ihre Shell-Anwendung neu oder starten Sie Ihren Computer neu. Wenn dies nicht funktioniert, müssen Sie möglicherweise $ PATH (Mac und Linux) oder PATH (Windows) bearbeiten und erneut starten.

Sowohl Node.js als auch NPM stimmen mit den beabsichtigten Versionen im obigen Terminal-Screenshot überein, sodass ich bereit bin, weiterzumachen und tatsächlich etwas mit Node.js zu entwickeln. Beginnen wir mit etwas, das mit reinem Knoten einfach zu erstellen ist.

Sie benötigen einen Code-Editor oder eine IDE, vorzugsweise einen, der JavaScript und Node.js wie Sublime Text, Visual Studio-Code, Brackets, Atom oder WebStorm unterstützt.

Node.js Beispiel: Ein einfacher Webserver

Um ganz einfach zu beginnen, stehlen wir ein einfaches Beispiel von der Node.js-Site. Kopieren Sie den Code und fügen Sie ihn in Ihren Code-Editor ein (ich verwende Visual Studio-Code, aber jeder Editor, der einfachen Text speichert, reicht aus). Speichern Sie ihn dann als example.js.

const http = require ('http');

const hostname = '127.0.0.1';

const port = 3000;

const server = http.createServer ((req, res) => {

   res.statusCode = 200;

   res.setHeader ('Content-Type', 'text / plain');

   res.end ('Hallo Welt \ n');

});

server.listen (port, hostname, () => {

   console.log (`Server läuft unter // $ {Hostname}: $ {Port} /`);

});

Öffnen Sie eine Shell in dem Verzeichnis, in dem Sie die Datei gespeichert haben, und führen Sie die Datei über die Befehlszeile aus:

$ node example.js

Server läuft unter //127.0.0.1:3000/

In meinem Fall habe ich das Terminalfenster in Visual Studio Code verwendet. Ich hätte fast genauso gut zu einem unabhängigen Shell-Fenster wechseln können.

Navigieren Sie nun zu der vom Server aufgelisteten URL:

Drücken Sie im Terminal die Strg-C-Taste, um den Knotenserver zu stoppen.

Bevor wir fortfahren, zerreißen wir den Code.

const http = require ('http');

In Zeile 1 wird verwendet require, wie Sie Module in Node.js laden. Die Anweisung lädt das http-Modul Node.js, das die createServerin den Zeilen 6 bis 10 listenaufgerufene Methode und die in den Zeilen 12 bis 14 aufgerufene Methode bereitstellt. Der Operator "Fettpfeil" =>in den Zeilen 6 und 12 ist eine Abkürzung zum Erstellen anonymer Lambda-Funktionen , die häufig in Node.js Apps verwendet werden.

const server = http.createServer ((req, res) => {

  res.statusCode = 200;

  res.setHeader ('Content-Type', 'text / plain');

  res.end ('Hallo Welt \ n');

});

Das resArgument createServer()in Zeile 6 wird verwendet, um die Antwort zu erstellen. Das reqArgument enthält die eingehende HTTP-Anforderung, die in diesem Code ignoriert wird. Die res.endMethode setzt die Antwortdaten auf 'Hello World \ n' und teilt dem Server mit, dass die Erstellung der Antwort abgeschlossen ist.

server.listen (port, hostname, () => {

  console.log (`Server läuft unter // $ {Hostname}: $ {Port} /`);

});

Der Server - Verschluss durch das erzeugte server.listen()Verfahren weist den Server für Anfragen auf dem definierten Host (127.0.0.1, zB localhost) und den Port (3000) zu hören. Der von der createServer()Methode erzeugte Abschluss verarbeitet die Anforderungen, wenn sie auf dem definierten Host und Port eingehen.

Die Idee, dass JavaScript-Schließungen als Ereignishandler definiert werden, ist einer der subtilsten und leistungsfähigsten Teile von Node.js und ein Schlüssel für die asynchrone nicht blockierende Architektur von Node. Node.js verbirgt seine Ereignisschleife, kehrt jedoch immer zur Behandlung von Ereignissen zurück, wenn nichts anderes aktiviert ist. Darüber hinaus verbrauchen JavaScript-Schließungen viel weniger Speicher als alternative Methoden zur Verarbeitung mehrerer Clientverbindungen, z. B. das Laichen von Threads oder das Verzweigen von Prozessen.

Beispiel für Node.j: Ein Webserver mit mehreren Prozessen

Abgesehen davon, dass nur "Hello World" gedruckt wird, wird das obige Beispiel nur in einem Thread ausgeführt, was bedeutet, dass nur ein Kern des Host-Computers verwendet werden kann. Es gibt Zeiten, in denen Sie viele Kerne haben, die Sie einem Server widmen möchten.

Das offizielle Beispiel für das Node-Cluster-Modul zeigt, wie dies behoben werden kann. Nach wie vor stehlen wir den Code und führen ihn aus. Navigieren Sie zur Clusterdokumentation von Node.js, kopieren Sie den Code, fügen Sie ihn in Ihren Code-Editor oder Ihre IDE ein und speichern Sie ihn als server.js.

const cluster = require ('cluster');

const http = require ('http');

const numCPUs = require ('os'). cpus (). length;

if (cluster.isMaster) {

console.log (`Master $ {process.pid} läuft`);

// Gabelarbeiter.

für (leti = 0; i

cluster.fork ();

}}

cluster.on ('exit', (Arbeiter, Code, Signal) => {

console.log (`worker $ {worker.process.pid} gestorben`);

});

} else {

// Arbeiter können jede TCP-Verbindung gemeinsam nutzen

// In diesem Fall handelt es sich um einen HTTP-Server

http.createServer ((req, res) => {

res.writeHead (200);

res.end (`Hallo Welt von $ {process.pid} \ n`);

}). listen (8000);

console.log (`Worker $ {process.pid} gestartet`);

}}

Wenn Sie node server.jsüber Ihre Befehlszeile ausführen , werden im Protokoll die Prozess-IDs für die Master- und Worker-Prozesse angezeigt. Es sollten so viele Mitarbeiter vorhanden sein, wie Ihr Computer über logische Kerne verfügt - acht für mein MacBook Pro mit seinem Core i7-Prozessor, der über vier Hardwarekerne und Hyper-Threading verfügt.

Wenn Sie zu localhost: 8000 oder 127.0.0.1:8000 navigieren, wird "Hallo Welt" angezeigt. Sie können im Terminalfenster Strg-C drücken, um die Knotenserverprozesse zu stoppen.

const cluster = require ('cluster');

const http = require ('http');

const numCPUs = require ('os'). cpus (). length;

Die Zeilen 1 und 2 sollten aus dem letzten Beispiel bekannt sein. Zeile 3 ist etwas anders. Anstatt nur das osModul zu benötigen , ruft es auch die cpus()Member-Funktion auf und gibt die Länge des zurückgegebenen Arrays zurück, dh die Anzahl der CPUs. Das Array selbst und die osModulverknüpfung sind dann nicht erreichbar und können zu einem späteren Zeitpunkt von der JavaScript-Engine gesammelt werden.

if (cluster.isMaster) {

   console.log (`Master $ {process.pid} läuft`);

   // Gabelarbeiter.

   für (sei i = 0; i <num CPUs; i ++) {

      cluster.fork ();

   }}

   cluster.on ('exit', (Arbeiter, Code, Signal) => {

      console.log (`worker $ {worker.process.pid} gestorben`);

   });

}}

Zeile 5 startet einen Block, der nur für den Master-Prozess ausgeführt wird. Es protokolliert seine PID, teilt den Worker pro verfügbarer CPU auf und erstellt einen Abschluss, um Cluster-Exit-Ereignisse zu verarbeiten und zu protokollieren.

} else {

   // Arbeiter können jede TCP-Verbindung gemeinsam nutzen

   // In diesem Fall handelt es sich um einen HTTP-Server

   http.createServer ((req, res) => {

      res.writeHead (200);

      res.end ('Hallo Welt \ n');

   }). listen (8000);

   console.log (`Worker $ {process.pid} gestartet`);

Der Block ab Zeile 16 wird nur von Worker-Prozessen ausgeführt. Dieser Code sollte aus dem vorherigen Beispiel bekannt sein: Er erstellt einen Webserver, der auf jede Anfrage mit "Hallo Welt" reagiert.

Aus der oben gezeigten Ausgabe geht hervor, dass dieser Code acht Mal auf meinem Computer ausgeführt wurde und acht Webserver-Mitarbeiter erstellt wurden, die die TCP-Verbindung des übergeordneten Prozesses auf Port 8000 gemeinsam nutzen. Aber wie teilt das System die Last unter ihnen auf?

In der Dokumentation heißt es, dass das Node.js-Clustermodul standardmäßig einen modifizierten Round-Robin-Algorithmus verwendet, außer unter Windows. Der Algorithmus wird von der cluster.schedulingPolicyEigenschaft gesteuert .

Woher wissen wir, dass dies funktioniert? Lass es uns testen. Es ist nur eine Codezeile erforderlich. Bearbeiten Sie Zeile 21, um Folgendes zu lesen:

      res.end (`Hallo Welt von $ {process.pid} \ n`);

Beachten Sie, dass Sie nicht nur hinzufügen müssen from ${process.pid}, sondern auch die Trennzeichen von einfachen Anführungszeichen in hintere Ticks ändern müssen, damit JavaScript die Zeichenfolge durch Variablen ersetzt.

Speichern Sie die Datei, stoppen Sie alle zuvor ausgeführten Instanzen und führen Sie sie erneut aus. Sie könnten denken, dass sich die zurückgegebene Prozess-ID jedes Mal ändert, wenn Sie Ihren Browser-Client aktualisieren, aber Sie würden sich irren. Der Browser ist zu intelligent, und wir haben die Webseite nicht als abgelaufen markiert, sodass der Browser die Antwort beim ersten Ausführen zwischenspeichert und weiterhin dieselbe Nummer anzeigt. Dies ist auch dann der Fall, wenn Sie mehrere Browser-Registerkarten oder Seiten erstellen, die auf dieselbe URL verweisen. Sie können jedoch sehen, dass das Round-Robin-Versenden vom Master funktioniert, indem mehrere Browser gleichzeitig ausgeführt werden, in diesem Fall Chrome, Safari und Opera:

Wenn Sie mit anderen Webservern vertraut sind, erwarten Sie möglicherweise ein Schema zum Weiterleiten von Anforderungen und zum Beibehalten des dauerhaften Status, um die Anmeldung und Umgebung jedes Benutzers in Node beizubehalten. Leider hat Node das nicht eingebaut. Fürchte dich nicht: Auf Node.js basieren zahlreiche Web-Frameworks, die alles tun, was du erwartest.

So installieren Sie ein Node.js-Modul mit NPM

Um die meisten Node-Module nutzen zu können, installieren Sie das Modul einfach aus der NPM-Registrierung, entweder global oder in einem Projektverzeichnis, und dann require()aus Ihrem Code. Oft hängt ein Projekt von mehreren NPM-Modulen ab und speichert diese Liste in der Datei project.json. Anstatt jede Abhängigkeit über die Befehlszeile zu installieren, können Sie sie alle gleichzeitig installieren, häufig nachdem Sie das Projekt aus dem GitHub-Repository ausgecheckt haben:

$

$ cd my_project

$ npm installieren

Nicht jedes NPM-Paket funktioniert genau so. Einige, einschließlich React, verfügen über "Factory" -Apps , mit denen Starter-Apps als eine ihrer Installationsoptionen erstellt werden können.

$ npm install -g create-react-app

$ cd ~ / work

$ create-react-app my-app

$ cd my-app /

$ npm starten

Es ist nicht ungewöhnlich, dass Tools global installiert werden. Beispielsweise wird das Angular-Befehlszeilentool Ng global installiert. Anschließend führen Sie es lokal aus, um eine App in einem Ordner zu erstellen.

$ npm install -g @ angle / cli

$ cd ~ / work

$ ng neue my-app

Angular hat zufällig eine andere Installationsmethode, die eher dem Standardmuster ähnelt. Das ist für den Angular QuickStart-Startwert:

$ git clone //github.com/angular/quickstart.git quickstart

$ cd Schnellstart

$ npm installieren

Die Datei package.json im Schnellstartordner weist npm installan, fast dieselbe Liste von Abhängigkeiten abzurufen wie die CLI-Installation.

Beispiel für Node.j: Ein Koa-Webserver

Während sowohl React als auch Angular Teil des Node.js-Ökosystems sind und Node.js und NPM für die Entwicklung benötigen, handelt es sich nicht speziell um Node.js-Frameworks - sie können in einem Browser ausgeführt werden. Ich habe Dutzende von aktuellen Node.js-Frameworks in "Vollständiger Leitfaden zu Node.js Frameworks" behandelt.

Beispielsweise ist Express der ursprünglich ausgearbeitete Node-Webserver, der die Webanwendung, HTTP-Anforderungen und -Antworten, das Routing und die Middleware verarbeitet. Eine neuere Option, Koa, verwendet Generatoren anstelle von Rückrufen für Middleware.

Sie installieren Koa mit dem Standardmuster in Ihrem App-Ordner:

$ npm koa installieren  

Unten finden Sie den Code für die Koa-App „Hello World“, die Sie wie in den vorherigen Beispielen speichern und ausführen können.

const Koa = erfordern ('koa');

const app = new Koa ();

// x-Antwortzeit

app.use (async (ctx, next) => {

const start = Date.now ();

warte auf next ();

const ms = Date.now () -start;

ctx.set ('X-Response-Time', `$ {ms} ms`);

});

// Logger

app.use (async (ctx, next) => {

const start = Date.now ();

warte auf next ();

const ms = Date.now () -start;

console.log (`$ {ctx.method} $ {ctx.url} - $ {ms}`);

});

// Antwort

app.use (async ctx => {

ctx.body = 'Hallo Welt';

});

app.listen (3000);

Es gibt einen Unterschied zwischen Middleware-Generatoren, wie sie von Koa verwendet werden, und Rückrufen, wie sie von Express und anderen Node.js-Frameworks verwendet werden. Viele Callback-Implementierungen durchlaufen die Steuerung einfach durch eine Reihe von Funktionen, bis man zurückkehrt, während Koa "Downstream" ergibt und die Steuerung dann "Upstream" zurückfließt.

Im obigen Beispiel "umschließt" die x-Antwortzeit den Antwortgenerator, wobei die  await next() Anweisung den Aufruf markiert. Die Verwendung dieser asynchronen Funktion ist flexibler als explizite Funktionsaufrufe, da sie es einfach macht, einen anderen Generator in die Sequenz einzufügen, beispielsweise einen Weblogger zwischen dem Timer und der Antwort.

Möglicherweise stoßen Sie auf älteren Koa-Code, der yield nextanstelle von verwendet wird await next(). Der Unterschied besteht darin, dass Koa jetzt ES2015- und Async-Funktionen unterstützt. Der Kontrollfluss läuft auf dasselbe hinaus: Er wechselt beim yield nextAufruf zum nächsten Handler in der Kette und kehrt dann zurück, wenn alle Handler fertig sind.