One place for hosting & domains

      Erstellen

      Erstellen eines Webservers in Node.js mit dem HTTP-Modul


      Der Autor hat den COVID-19 Relief Fund dazu ausgewählt, eine Spende im Rahmen des Programms Write for DOnations zu erhalten.

      Einführung

      Wenn Sie eine Webseite in Ihrem Browser anzeigen, stellen Sie eine Anfrage über das Internet an einen anderen Computer, der Ihnen dann die Webseite als Antwort bereitstellt. Dieser Computer, mit dem Sie über das Internet kommunizieren, ist ein Webserver. Ein Webserver empfängt HTTP-Anfragen von einem Client (wie Ihrem Browser) und stellt eine HTTP-Antwort bereit, z. B. eine HTML-Seite oder JSON aus einer API.

      Am Zurückgeben einer Webseite durch einen Server sind verschiedene Softwareanwendungen beteiligt. Diese Software fällt im Allgemeinen in zwei Kategorien: Frontend und Backend. Frontend-Code befasst sich damit, wie Inhalte dargestellt werden, z. B. die Farbe einer Navigationsleiste und der Textstil. Backend-Code befasst sich damit, wie Daten ausgetauscht, verarbeitet und gespeichert werden. Code, der Netzwerkanfragen von Ihrem Browser behandelt oder mit der Datenbank kommuniziert, wird in erster Linie mit Backend-Code verwaltet.

      Mit Node.js können Entwickler JavaScript zum Schreiben von Backend-Code nutzen, auch wenn die Umgebung im Browser traditionell verwendet wurde, um Frontend-Code zu schreiben. Wenn Frontend und Backend so nah beieinander sind, verringert sich der Aufwand bei der Einrichtung eines Webservers. Das ist ein Grund dafür, warum Node.js eine beliebte Wahl zum Schreiben von Backend-Code ist.

      In diesem Tutorial lernen Sie, wie Sie Webserver mit dem in Node.js enthaltenen http-Modul einrichten können. Sie werden Webserver erstellen, die JSON-Daten, CSV-Dateien und HTML-Webseiten zurückgeben können.

      Voraussetzungen

      Schritt 1 — Einrichten eines grundlegenden HTTP-Servers

      Beginnen wir zunächst mit der Einrichtung eines Servers, der dem Benutzer Klartext zurückgibt. Damit werden die zur Einrichtung eines Servers erforderlichen Schlüsselkonzepte behandelt, was als Grundlage für die Rückgabe komplexer Datenformate wie JSON dient.

      Zuerst müssen wir eine zugängliche Codierungsumgebung einrichten, um unsere Übungen sowie andere Aufgaben in dem Artikel ausführen zu können. Erstellen Sie im Terminal einen Ordner namens first-servers:

      Gehen Sie dann in diesen Ordner hinein:

      Erstellen Sie nun die Datei, die den Code beinhalten wird:

      Öffnen Sie die Datei in einem Texteditor. Wir verwenden nano, da es im Terminal verfügbar ist:

      Wir starten mit dem Laden des http-Moduls, das bei allen Node.js-Installationen Standard ist. Fügen Sie die folgende Zeile zu hello.js hinzu:

      first-servers/hello.js

      const http = require("http");
      

      Das Modul http enthält die Funktion zur Erstellung des Servers, wie wir später sehen werden. Wenn Sie mehr über Module in Node.js erfahren möchten, lesen Sie unseren Artikel Erstellen eines Node.js-Moduls.

      Unser nächster Schritt besteht darin, zwei Konstanten zu definieren, also den Host und den Port, an die unser Server gebunden ist:

      first-servers/hello.js

      ...
      const host="localhost";
      const port = 8000;
      

      Wie bereits erwähnt, akzeptieren Webserver Anfragen von Browsern und anderen Clients. Wir können mit einem Webserver interagieren, indem wir einen Domänennamen eingeben, der über einen DNS-Server in eine IP-Adresse übersetzt wird. Eine IP-Adresse ist eine eindeutige Sequenz von Zahlen, die einen Rechner in einem Netzwerk wie dem Internet identifiziert. Weitere Informationen zu Domänennamenkonzepten finden Sie in unserem Artikel Eine Einführung in DNS-Begriffe, -Komponenten und -Konzepte.

      Der Wert localhost ist eine spezielle private Adresse, die Computer zum Verweisen auf sich selbst verwenden. Es handelt sich dabei typischerweise um das Äquivalent der internen IP-Adresse 127.0.0.1 und ist nur für den lokalen Computer verfügbar, nicht für die lokalen Netzwerke, mit denen wir verbunden sind, oder mit dem Internet.

      Der Port ist eine Zahl, die Server als Endpunkt oder „Tür“ zu unserer IP-Adresse verwenden. In unserem Beispiel verwenden wir Port 8000 für unseren Webserver. Ports 8080 und 8000 dienen typischerweise als Standardports für die Entwicklung, und meist nutzen Entwickler sie anstelle anderer Ports für HTTP-Server.

      Wenn wir unseren Server an diesen Host und Port binden, können wir unseren Server erreichen, indem wir in einem lokalen Browser http://localhost:8000 aufrufen.

      Lassen Sie uns eine spezielle Funktion hinzufügen, die wir in Node.js einen Request Listener nennen. Diese Funktion dient dazu, eine eingehende HTTP-Anfrage zu bearbeiten und eine HTTP-Antwort zurückzugeben. Diese Funktion muss zwei Argumente aufweisen: ein Anfrageobjekt und ein Antwortobjekt. Das Anfrageobjekt erfasst alle eingehenden Daten der HTTP-Anforderung. Das Antwortobjekt dient der Rückgabe von HTTP-Antworten an den Server.

      Wir möchten, dass unser erster Server folgende Nachricht zurückgibt, wenn jemand darauf zugreift: „My first server!".

      Fügen wir als Nächstes diese Funktion hinzu:

      first-servers/hello.js

      ...
      
      const requestListener = function (req, res) {
          res.writeHead(200);
          res.end("My first server!");
      };
      

      Die Funktion würde normalerweise nach dem benannt, was sie tut. Wenn wir zum Beispiel eine Request Listener-Funktion erstellen, um eine Liste von Büchern zurückzugeben, würden wir sie wahrscheinlich listBooks() nennen. Da dies ein Beispielfall ist, verwenden wir den allgemeinen Namen requestListener.

      Alle Request Listener-Funktionen in Node.js akzeptieren zwei Argumente: req und res (wir können sie anders nennen, wenn wir möchten). Die HTTP-Anfrage, die der Benutzer sendet, wird in einem Anfrageobjekt erfasst. Das entspricht dem ersten Argument req. Die HTTP-Antwort, die wir an den Benutzer zurückgeben, wird gebildet, indem wir mit dem Antwortobjekt im zweiten Argument res interagieren.

      Die erste Zeile res.writeHead(200); legt den HTTP-Statuscode der Antwort fest. HTTP-Statuscodes geben an, wie gut eine HTTP-Anfrage vom Server bearbeitet wurde. In diesem Fall entspricht der Statuscode 200 „OK“. Wenn Sie mehr über die verschiedenen HTTP-Codes, die Ihre Webserver zurückgeben können, und ihre jeweilige Bedeutung erfahren möchten, ist unser Leitfaden Fehlerbehebung für gängige HTTP-Fehlercodes ein perfekter Ausgangspunkt.

      Die nächste Zeile der Funktion res.end("My fist server!") ; schreibt die HTTP-Antwort zurück an den Client, der sie angefordert hat. Diese Funktion gibt alle Daten zurück, die der Server zurückgeben muss. In diesem Fall werden Textdaten zurückgegeben.

      Abschließend können wir unseren Server erstellen und unseren Request Listener verwenden:

      first-servers/hello.js

      ...
      
      const server = http.createServer(requestListener);
      server.listen(port, host, () => {
          console.log(`Server is running on http://${host}:${port}`);
      });
      

      Speichern und schließen Sie nano, indem Sie Strg+X drücken.

      In der ersten Zeile erstellen wir ein neues Server-Objekt über die Funktion createServer() des http-Moduls. Dieser Server akzeptiert HTTP-Anfragen und übergibt sie an unsere Funktion requestListener().

      Nachdem wir unseren Server erstellt haben, müssen wir ihn nun an eine Netzwerkadresse binden. Das tun wir mit der Methode server.listen(). Sie akzeptiert drei Argumente: Port, Host und eine Rückruffunktion, die ausgelöst wird, sobald der Server mit dem Lauschen beginnt.

      Alle diese Argumente sind optional; es ist aber eine gute Idee, explizit zu bestätigen, welchen Port und Host ein Webserver verwenden soll. Wenn Sie Webserver in verschiedenen Umgebungen bereitstellen, müssen Sie den Port und den Host kennen, bei denen sie ausgeführt werden, um den Lastausgleich oder einen DNS-Alias einzurichten.

      Die Rückruffunktion protokolliert eine Nachricht an unsere Konsole, damit wir wissen, wann der Server mit dem Lauschen nach Verbindungen begonnen hat.

      Anmerkung: Obwohl requestListener() das Objekt req nicht nutzt, muss es dennoch das erste Argument der Funktion sein.

      Mit weniger als fünfzehn Codezeilen verfügen wir nun über einen Webserver. Lassen Sie uns das in der Praxis ansehen und durchgängig testen, indem wir folgendes Programm ausführen:

      In der Konsole sehen wir diese Ausgabe:

      Output

      Server is running on http://localhost:8000

      Beachten Sie, dass die Eingabeaufforderung verschwindet. Das liegt daran, dass ein Node.js-Server ein lang laufender Vorgang ist. Der Server wird nur dann beendet, wenn ein Fehler auftritt, der zum Absturz des Servers führt, oder wenn wir den Node.js-Prozess anhalten, der den Server ausführt.

      In einem separaten Terminalfenster kommunizieren wir mit dem Server über cURL, ein CLI-Tool zur Übertragung von Daten an und aus einem Netzwerk. Geben Sie den Befehl ein, um eine HTTP-GET-Anfrage an unseren laufenden Server zu stellen:

      • curl http://localhost:8000

      Wenn wir ENTER drücken, zeigt unser Terminal die folgende Ausgabe:

      Output

      My first server!

      Wir haben nun einen Server eingerichtet und unsere erste Serverantwort erhalten.

      Lassen Sie uns genau ansehen, was passiert ist, als wir unseren Server getestet haben. Mit cURL haben wir eine GET-Anfrage an den Server bei http://localhost:8000 gesendet. Unser Node.js-Server hat nach Verbindungen von dieser Adresse gelauscht. Der Server hat diese Anfrage an die Funktion requestListener() übergeben. Die Funktion hat Textdaten mit dem Statuscode 200 zurückgegeben. Der Server hat diese Antwort dann an cURL zurückgesendet, wodurch die Nachricht in unserem Terminal angezeigt wurde.

      Bevor wir fortfahren, beenden wir unseren laufenden Server, indem wir Strg+C drücken. Dadurch wird die Ausführung unseres Servers unterbrochen und wir kehren zur Befehlszeilenaufforderung zurück.

      Bei den wenigstens Websites, die wir besuchen, oder APIs, die wir verwenden, werden Serverantworten in Klartext dargestellt. HTML-Seiten und JSON-Daten sind gängige Antwortformate. Im nächsten Schritt erfahren wir, wie sich HTTP-Antworten in gängigen Datenformaten zurückgeben lassen, die im Web genutzt werden.

      Schritt 2 — Zurückgeben verschiedener Arten von Inhalten

      Die Antwort, die wir von einem Webserver zurückgeben, kann eine Vielzahl von Formaten aufweisen. JSON und HTML wurden bereits erwähnt; wir können aber auch andere Textformate wie XML und CSV zurückgeben. Schließlich können Webserver Nicht-Text-Daten wie PDFs, gezippte Dateien, Audio und Video zurückgeben.

      In diesem Artikel lernen Sie, wie Sie neben dem gerade zurückgegebenen Klartext die folgenden Arten von Daten zurückgeben:

      Diese drei Datentypen sind alle textbasiert und beliebte Formate für die Bereitstellung von Inhalten im Web. Viele serverseitige Entwicklungssprachen und Tools bieten Unterstützung für die Rückgabe dieser verschiedenen Datentypen. Im Kontext von Node.js müssen wir zwei Dinge tun:

      1. Den Header Content-Type in unseren HTTP-Antworten mit dem entsprechenden Wert festlegen.
      2. Sicherstellen, dass res.end() die Daten im richtigen Format erhält.

      Lassen Sie uns dies mit einigen Beispielen in der Praxis ansehen. Der Code, den wir in diesem Abschnitt schreiben werden, sowie spätere Codes haben viele Ähnlichkeiten mit dem zuvor geschriebenen Code. Die meisten Änderungen gibt es innerhalb der Funktion requestListener(). Lassen Sie uns Dateien mit diesem „Vorlagencode“ erstellen, um zukünftige Abschnitte leichter folgbar zu machen.

      Erstellen Sie eine neue Datei namens html.js: Diese Datei wird später verwendet, um in einer HTTP-Antwort HTML-Text zurückzugeben. Wir platzieren den Vorlagencode hier und kopieren ihn auf die anderen Server, die verschiedene Arten zurückgeben.

      Geben Sie im Terminal Folgendes ein:

      Öffnen Sie diese Datei nun in einem Texteditor:

      Kopieren wir den „Vorlagencode“​​. Geben Sie Folgendes in nano ein:

      first-servers/html.js

      const http = require("http");
      
      const host="localhost";
      const port = 8000;
      
      const requestListener = function (req, res) {};
      
      const server = http.createServer(requestListener);
      server.listen(port, host, () => {
          console.log(`Server is running on http://${host}:${port}`);
      });
      

      Speichern und schließen Sie html.js mit Strg+X und kehren Sie dann zum Terminal zurück.

      Lassen Sie uns diese Datei nun in zwei neue Dateien kopieren. Die erste Datei wird dazu dienen, CSV-Daten in der HTTP-Antwort zurückzugeben:

      Die zweite Datei wird eine JSON-Antwort im Server zurückgegeben:

      Die verbleibenden Dateien werden für spätere Übungen benötigt:

      • cp html.js htmlFile.js
      • cp html.js routes.js

      Wir sind nun bereit, um unsere Übungen fortzusetzen. Lassen Sie uns mit der Rückgabe von JSON beginnen.

      Bereitstellen von JSON

      JavaScript Object Notation, allgemein als JSON bezeichnet, ist ein textbasiertes Format für den Datenaustausch. Wie der Name bereits andeutet, wird es von JavaScript-Objekten abgeleitet, ist aber sprachunabhängig und lässt sich von jeder Programmiersprache verwenden, die seine Syntax parsen kann.

      JSON wird häufig von APIs verwendet, um Daten zu akzeptieren und zurückzugeben. Die hohe Popularität beruht auf einer geringeren Datenübertragungsgröße als bei älteren Datenaustauschstandards wie XML sowie auf dem vorhandenen Tooling, mit dem Programme JSON ohne übermäßigen Aufwand parsen können. Wenn Sie mehr über JSON erfahren möchten, können Sie unseren Leitfaden Arbeiten mit JSON in JavaScript lesen.

      Öffnen Sie die Datei json.js mit nano:

      Wir möchten eine JSON-Antwort zurückgeben. Lassen Sie uns die Funktion requestListener() so anpassen, dass der entsprechende Header aller JSON-Antworten zurückgegeben wird, indem wir die hervorgehobenen Zeilen folgendermaßen ändern:

      first-servers/json.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "application/json");
      };
      ...
      

      Die Methode res.setHeader() fügt der Antwort einen HTTP-Header hinzu. HTTP-Header sind zusätzliche Informationen, die an eine Anfrage oder Antwort angehängt werden können. Die Methode res.setHeader() benötigt zwei Argumente: den Namen des Headers und seinen Wert.

      Der Header Content-Type dient zum Anzeigen des Formats der Daten (auch als Medientyp bekannt), die mit der Anfrage oder Antwort gesendet werden. In diesem Fall ist unser Content-Type application/json.

      Lassen Sie uns nun JSON-Inhalt an den Benutzer zurückgeben. Ändern Sie json.js, damit die Datei folgendermaßen aussieht:

      first-servers/json.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "application/json");
          res.writeHead(200);
          res.end(`{"message": "This is a JSON response"}`);
      };
      ...
      

      Wie zuvor sagen wir dem Benutzer, dass seine Anfrage erfolgreich war, indem wir einen Statuscode von 200 zurückgeben. Dieses Mal enthält unser Zeichfolgenargument im Aufruf response.end() gültiges JSON.

      Speichern und schließen Sie json.js, indem Sie Strg+X drücken. Lassen Sie uns nun den Server mit dem Befehl node ausführen:

      In einem anderen Terminal stellen wir eine Verbindung zum Server her, indem wir cURL verwenden:

      • curl http://localhost:8000

      Wenn wir ENTER drücken, sehen wir folgendes Ergebnis:

      Output

      {"message": "This is a JSON response"}

      Wir haben nun erfolgreich eine JSON-Antwort zurückgegeben, genauso wie viele der beliebten APIs, mit denen wir Apps einrichten. Beenden Sie den laufenden Server unbedingt mit Strg+C, damit wir zur standardmäßigen Terminalaufforderung zurückkehren können. Lassen Sie uns als Nächstes ein weiteres beliebtes Format zum Zurückgeben von Daten ansehen: CSV.

      Bereitstellen von CSV

      Das Dateiformat Comma Separated Values (CSV) ist ein Textstandard, der häufig für die Bereitstellung von Tabellendaten verwendet wird. In den meisten Fällen wird jede Zeile durch ein Neue-Zeile-Symbol und jedes Element in der Zeile durch ein Komma getrennt.

      Öffnen Sie in unserem Arbeitsbereich mit einem Texteditor die Datei csv.js:

      Lassen Sie uns die folgenden Zeilen in unsere Funktion requestListener() einfügen:

      first-servers/csv.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "text/csv");
          res.setHeader("Content-Disposition", "attachment;filename=oceanpals.csv");
      };
      ...
      

      Dieses Mal zeigt unser Content-Type an, dass eine CSV-Datei zurückgegeben wird, da der Wert text/csv lautet. Der zweite Header, den wir hinzufügen, ist Content-Disposition. Dieser Header teilt dem Browser mit, wie die Daten angezeigt werden sollen, insbesondere im Browser oder als separate Datei.

      Wenn wir CSV-Antworten zurückgeben, laden die meisten modernen Browser die Datei automatisch herunter, selbst wenn der Header Content-Disposition nicht gesetzt ist. Wenn wir aber eine CSV-Datei zurückgeben, sollten wir diesen Header weiterhin hinzufügen, da er uns ermöglicht, den Namen der CSV-Datei festzulegen. In diesem Fall signalisieren wir dem Browser, dass diese CSV-Datei ein Anhang ist und heruntergeladen werden soll. Dann teilen wir dem Browser mit, dass der Name der Datei oceanpals.csv lautet.

      Lassen Sie uns die CSV-Daten in die HTTP-Antwort schreiben:

      first-servers/csv.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "text/csv");
          res.setHeader("Content-Disposition", "attachment;filename=oceanpals.csv");
          res.writeHead(200);
          res.end(`id,name,emailn1,Sammy Shark,shark@ocean.com`);
      };
      ...
      

      Wie zuvor geben wir mit unserer Antwort einen 200/OK-Status zurück. Dieses Mal verfügt unser Aufruf an res.end() über eine Zeichenfolge, die eine gültige CSV ist. Das Komma trennt den Wert in den einzelnen Spalten, während das Neue-Zeile-Zeichen (n) die Zeilen trennt. Wir verfügen über zwei Zeilen, eine für den Tabellen-Header und eine für die Daten.

      Wir testen diesen Server im Browser. Speichern Sie csv.js und schließen Sie den Editor mit Strg+X.

      Führen Sie den Server mit dem Befehl Node.js aus:

      In einem anderen Terminal stellen wir eine Verbindung zum Server her, indem wir cURL verwenden:

      • curl http://localhost:8000

      Das wird in der Konsole angezeigt:

      Output

      id,name,email 1,Sammy Shark,shark@ocean.com

      Wenn wir in unserem Browser http://localhost:8000 aufrufen, wird eine CSV-Datei heruntergeladen. Ihr Dateiname wird oceanpals.csv lauten.

      Beenden Sie den laufenden Server mit Strg+C, um zur standardmäßigen Terminalaufforderung zurückzukehren.

      Mit der Rückgabe von JSON und CSV haben wir zwei Fälle behandelt, die bei APIs beliebt sind. Lassen Sie uns mit der Ansicht fortfahren, die Benutzer von Websites in einem Browser sehen.

      Bereitstellen von HTML

      HTML (HyperText Markup Language) ist das gängigste Format, das verwendet wird, wenn wir wollen, dass Benutzer über einen Webbrowser mit unserem Server interagieren. Es dient dazu, Webinhalte zu strukturieren. Webbrowser dienen zum Anzeigen von HTML-Inhalten sowie beliebiger Stile, die wir mit CSS hinzufügen, einer anderen Frontend-Webtechnologie, mit der wir das Aussehen unserer Websites ändern können.

      Lassen Sie uns die Datei html.js mit unserem Texteditor erneut öffnen:

      Ändern Sie die Funktion requestListener(), um den entsprechenden Content-Type-Header für eine HTML-Antwort zurückzugeben:

      first-servers/html.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "text/html");
      };
      ...
      

      Lassen Sie uns nun HTML-Inhalt an den Benutzer zurückgeben. Fügen Sie die hervorgehobenen Zeilen in html.js hinzu, damit die Datei folgendermaßen aussieht:

      first-servers/html.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "text/html");
          res.writeHead(200);
          res.end(`<html><body><h1>This is HTML</h1></body></html>`);
      };
      ...
      

      Wir fügen zuerst den HTTP-Statuscode ein. Dann rufen wir response.end() mit einem Zeichenfolgenargument auf, das gültiges HTML enthält. Wenn wir im Browser auf unseren Server zugreifen, sehen wir eine HTML-Seite mit einem Header-Tag, das den Inhalt This is HTML aufweist.

      Speichern und schließen Sie Datei, indem Sie Strg+X drücken. Lassen Sie uns nun den Server mit dem Befehl node ausführen:

      Wir sehen Server is running on http://localhost:8000, sobald unser Programm gestartet wurde.

      Rufen Sie nun im Browser http://localhost:8000 auf. Unsere Seite wird so aussehen:

      Bild der vom Node.js-Server zurückgegebenen HTML-Antwort

      Beenden Sie den laufenden Server mit Strg+C, um zur standardmäßigen Terminalaufforderung zurückzukehren.

      Es ist üblich, dass HTML in einer Datei geschrieben wird, getrennt vom serverseitigen Code (wie unsere Node.js-Programme). Lassen Sie uns als Nächstes sehen, wie wir HTML-Antworten aus Dateien zurückgeben können.

      Schritt 3 — Bereitstellen einer HTML-Seite aus einer Datei

      Wir können dem Benutzer HTML als Zeichenfolgen in Node.js bereitstellen, es ist jedoch empfehlenswert, HTML-Dateien zu laden und ihren Inhalt bereitzustellen. Wenn die HTML-Datei wächst, müssen wir so keine langen Zeichenfolgen in unserem Node.js-Code pflegen. Dadurch bleibt der Code kurz und können wir getrennt an den einzelnen Aspekten unserer Website arbeiten. Diese „Trennung von Aufgaben“ ist in vielen Webentwicklungs-Setups üblich; daher ist es gut zu wissen, wie HTML-Dateien zur Unterstützung in Node.js geladen werden.

      Um HTML-Dateien bereitzustellen, laden wir die HTML-Datei mit dem fs-Modul und verwenden ihre Daten beim Schreiben unserer HTTP-Antwort.

      Zuerst erstellen wir eine HTML-Datei, die der Webserver zurückgeben wird. Erstellen Sie eine neue HTML-Datei:

      Öffnen Sie nun index.html in einem Texteditor:

      Unsere Webseite wird minimal sein. Sie wird über einen orangen Hintergrund verfügen und in der Mitte einen Grußtext anzeigen. Fügen Sie diesen Code in die Datei ein:

      first-servers/index.html

      <!DOCTYPE html>
      
      <head>
          <title>My Website</title>
          <style>
              *,
              html {
                  margin: 0;
                  padding: 0;
                  border: 0;
              }
      
              html {
                  width: 100%;
                  height: 100%;
              }
      
              body {
                  width: 100%;
                  height: 100%;
                  position: relative;
                  background-color: rgb(236, 152, 42);
              }
      
              .center {
                  width: 100%;
                  height: 50%;
                  margin: 0;
                  position: absolute;
                  top: 50%;
                  left: 50%;
                  transform: translate(-50%, -50%);
                  color: white;
                  font-family: "Trebuchet MS", Helvetica, sans-serif;
                  text-align: center;
              }
      
              h1 {
                  font-size: 144px;
              }
      
              p {
                  font-size: 64px;
              }
          </style>
      </head>
      
      <body>
          <div class="center">
              <h1>Hello Again!</h1>
              <p>This is served from a file</p>
          </div>
      </body>
      
      </html>
      

      Diese einzelne Webseite zeigt zwei Textzeilen an: Hello Again! und This is served from a file. Die Zeilen befinden sich in der Mitte der Seite übereinander. Die erste Zeile des Texts wird als Überschrift angezeigt. Das bedeutet, dass sie größer ist. Die zweite Zeile des Texts wird etwas kleiner erscheinen. Der gesamte Text wird weiß dargestellt, während die Webseite einen orangen Hintergrund hat.

      Es ist zwar nicht Inhalt dieses Artikel oder dieser Reihe, Sie können bei Bedarf aber mehr über HTML, CSS und andere Frontend-Webtechnologien erfahren, indem Sie einen Blick in den Leitfaden Erste Schritte mit dem Web von Mozilla werfen.

      Das ist alles, was wir für HTML benötigen. Speichern und schließen Sie die Datei also mit Strg+X. Wir können nun mit dem Servercode fortfahren.

      Für diese Übung werden wir mit htmlFile.js arbeiten. Öffnen Sie die Datei mit dem Texteditor:

      Da wir eine Datei lesen müssen, beginnen wir, indem wir das fs-Modul importieren:

      first-servers/htmlFile.js

      const http = require("http");
      const fs = require('fs').promises;
      ...
      

      Dieses Modul enthält eine readFile()-Funktion, die wir zum Laden der HTML-Datei verwenden werden. Wir importieren die Zusagevariante anhand aktueller Best Practices für JavaScript. Wir verwenden Zusagen, da sie syntaktisch prägnanter sind als Rückrufe. Diese müssten wir verwenden, wenn wir fs lediglich require('fs') zuordnen. Weitere Informationen über Best Practices für asynchrone Programmierung finden Sie in unserem Leitfaden Schreiben von asynchronem Code in Node.js.

      Wir möchten, dass unsere HTML-Datei gelesen wird, wenn ein Benutzer eine Anfrage an unser System stellt. Lassen Sie uns mit dem Ändern von requestListener() zum Lesen der Datei beginnen:

      first-servers/htmlFile.js

      ...
      const requestListener = function (req, res) {
          fs.readFile(__dirname + "/index.html")
      };
      ...
      

      Wir verwenden die Methode fs.readFile(), um die Datei zu laden. Ihr Argument lautet __dirname + "/index.html" Der spezielle Variable __dirname weist den absoluten Pfad auf, an dem der Node.js-Code ausgeführt wird. Dann hängen wir /index.html an, damit wir die zuvor erstellte HTML-Datei laden können.

      Lassen Sie uns nun die HTML-Seite zurückgeben, sobald sie geladen ist:

      first-servers/htmlFile.js

      ...
      const requestListener = function (req, res) {
          fs.readFile(__dirname + "/index.html")
              .then(contents => {
                  res.setHeader("Content-Type", "text/html");
                  res.writeHead(200);
                  res.end(contents);
              })
      };
      ...
      

      Wenn das Versprechen fs.readFile() erfolgreich aufgelöst wird, werden deren Daten zurückgegeben. Wir verwenden die Methode then(), um diesen Fall zu handhaben. Der Parameter contents enthält die Daten der HTML-Datei.

      Wir setzen zunächst den Header Content-Type auf text/html, um dem Client zu sagen, dass wir HTML-Daten zurückgeben. Wir schreiben dann den Statuscode, um anzuzeigen, dass die Anfrage erfolgreich war. Abschließend senden wir dem Client die geladene HTML-Seite mit den Daten in der Variablen contents.

      Die Methode fs.readFile() kann manchmal fehlschlagen. Daher sollten wir den Fall handhaben, wenn wir einen Fehler erhalten. Fügen Sie Folgendes in die Funktion requestListener() ein:

      first-servers/htmlFile.js

      ...
      const requestListener = function (req, res) {
          fs.readFile(__dirname + "/index.html")
              .then(contents => {
                  res.setHeader("Content-Type", "text/html");
                  res.writeHead(200);
                  res.end(contents);
              })
              .catch(err => {
                  res.writeHead(500);
                  res.end(err);
                  return;
              });
      };
      ...
      

      Speichern Sie die Datei und schließen Sie nano mit Strg+X.

      Wenn ein Versprechen auf einen Fehler trifft, wird es verworfen. Wir behandeln diesen Fall mit der Methode catch(). Sie akzeptiert den Fehler, den fs.readFile() zurückgibt, legt den Statuscode auf 500 fest, was bedeutet, dass ein interner Fehler aufgetreten ist, und gibt den Fehler an den Benutzer zurück.

      Führen Sie unseren Server mit dem Befehl node aus:

      Rufen Sie im Webbrowser http://localhost:8000 auf. Sie sehen diese Seite:

      Bild der aus einer Datei in Node.js geladenen HTML-Seite

      Sie haben nun eine HTML-Seite vom Server an den Benutzer zurückgegeben. Sie können den laufenden Server mit Strg+C beenden. Wenn Sie dies tun, wird Ihnen die Eingabeaufforderung des Terminals angezeigt.

      Wenn Sie in der Produktion Code wie hier verfassen, wollen Sie vielleicht nicht jedesmal eine HTML-Seite laden, wenn Sie eine HTTP-Anfrage erhalten. Zwar ist diese HTML-Seite nur etwa 800 Byte groß, doch können komplexere Websites Größen im Megabytebereich aufweisen. Große Dateien können eine Weile zum Laden benötigen. Wenn Ihre Website eine Menge Datenverkehr erwartet, kann es am besten sein, HTML-Dateien beim Starten zu laden und ihren Inhalt zu speichern. Nachdem sie geladen wurden, können Sie den Server einrichten und ihn an einer Adresse auf Anfragen lauschen lassen.

      Um diese Methode zu demonstrieren, sehen wir uns an, wie wir unseren Server so anpassen können, dass er effizienter und besser skalierbar wird.

      Effizientes Bereitstellen von HTML

      Anstatt die HTML für jede Anfrage zu laden, laden wir sie in diesem Schritt nur einmal am Anfang. Die Anfrage gibt die beim Starten geladenen Daten zurück.

      Öffnen Sie im Terminal mit einem Texteditor erneut das Skript Node.js:

      Lassen Sie uns zunächst eine neue Variable hinzufügen, bevor wir die Funktion requestListener() erstellen:

      first-servers/htmlFile.js

      ...
      let indexFile;
      
      const requestListener = function (req, res) {
      ...
      

      Wenn wir dieses Programm ausführen, wird diese Variable den Inhalt der HTML-Datei enthalten.

      Lassen Sie uns nun die Funktion requestListener() anpassen. Anstatt die Datei zu laden, gibt sie nun den Inhalt von indexFile zurück:

      first-servers/htmlFile.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "text/html");
          res.writeHead(200);
          res.end(indexFile);
      };
      ...
      

      Als Nächstes verschieben wir die Logik zum Dateilesen von der Funktion requestListener() in den Start unseres Servers. Nehmen Sie beim Erstellen des Servers die folgenden Änderungen vor:

      first-servers/htmlFile.js

      ...
      
      const server = http.createServer(requestListener);
      
      fs.readFile(__dirname + "/index.html")
          .then(contents => {
              indexFile = contents;
              server.listen(port, host, () => {
                  console.log(`Server is running on http://${host}:${port}`);
              });
          })
          .catch(err => {
              console.error(`Could not read index.html file: ${err}`);
              process.exit(1);
          });
      

      Speichern Sie die Datei und schließen Sie nano mit Strg+X.

      Der Code, der die Datei liest, ähnelt dem, was wir bei unserem ersten Versuch geschrieben haben. Nachdem wir die Datei erfolgreich gelesen haben, speichern wir den Inhalt jedoch in unserer globalen Variable indexFile. Dann starten wir den Server mit der Methode listen(). Das Entscheidende ist, dass die Datei geladen wird, bevor der Server ausgeführt wird. Auf diese Weise wird die Funktion requestListener() eine HTML-Seite zurückgeben, da indexFile keine leere Variable mehr ist.

      Unsere Fehlerhandlung hat sich auch geändert. Wenn die Datei nicht geladen werden kann, erfassen wir den Fehler und geben ihn in unserer Konsole aus. Dann beenden wir das Node.js-Programm mit der Funktion exit(), ohne den Server zu starten. So können wir sehen, warum das Lesen der Datei fehlgeschlagen ist, das Problem adressieren und dann den Server neu starten.

      Wir haben nun verschiedene Webserver erstellt, die verschiedene Arten von Daten an einen Benutzer zurückgeben. Bisher haben wir keine Anfragedaten verwendet, um zu bestimmen, was zurückgegeben werden soll. Wir müssen Anfragedaten verwenden, wenn wir verschiedene Routen oder Wege in einem Node.js-Server einrichten. Lassen Sie uns also als Nächstes betrachten, wie diese zusammenarbeiten.

      Schritt 4 — Verwalten von Routen mit einem HTTP-Anfrageobjekt

      Die meisten Websites, die wir besuchen, oder APIs, die wir verwenden, weisen normalerweise mehr als einen Endpunkt auf, sodass wir auf verschiedene Ressourcen zugreifen können. Ein gutes Beispiel dafür wäre ein Buchverwaltungssystem, das in einer Bücherei zum Einsatz kommt. Es müsste nicht nur Buchdaten verwalten, sondern auch Autorendaten, um das Angebot zu katalogisieren und Suchen möglichst einfach zu gestalten.

      Zwar sind die Daten für Bücher und Autoren verwandt, doch sind sie zwei verschiedene Objekte. In diesem Fall codieren Softwareentwickler meist jedes Objekt auf verschiedenen Endpunkten, um den API-Benutzern zu zeigen, mit welchen Arten von Daten sie interagieren.

      Lassen Sie uns einen neuen Server für eine kleine Bücherei erstellen, der zwei verschiedene Arten von Daten zurückgibt. Wenn Benutzer die Adresse unseres Servers unter /books aufrufen, erhalten Sie eine Liste von Büchern in JSON. Wenn sie zu /authors gehen, erhalten sie eine Liste von Autorendaten in JSON.

      Bisher haben wir auf jede Anfrage, die wir erhalten haben, die gleiche Antwort zurückgegeben. Lassen Sie uns das kurz illustrieren.

      Führen Sie unser JSON-Antwortbeispiel erneut aus:

      Lassen Sie uns wie zuvor in einem anderen Terminal eine cURL-Anfrage ausführen:

      • curl http://localhost:8000

      Sie sehen:

      Output

      {"message": "This is a JSON response"}

      Lassen Sie uns nun einen weiteren cURL-Befehl ausprobieren:

      • curl http://localhost:8000/todos

      Nach dem Drücken von Enter sehen Sie das gleiche Ergebnis:

      Output

      {"message": "This is a JSON response"}

      Wir haben keine spezielle Logik in unserer Funktion requestListener() zur Bearbeitung einer Anfrage erstellt, deren URL /todos enthält, sodass Node.js standardmäßig die gleiche JSON-Nachricht zurückgibt.

      Da wir einen Miniaturserver zur Buchverwaltung erstellen möchten, trennen wir nun die Art von Daten, die zurückgegeben werden sollen, je nach Endpunkt der Benutzerzugriffe.

      Beenden Sie zuerst den laufenden Server mit Strg+C.

      Öffnen Sie nun routes.js in Ihrem Texteditor:

      Lassen Sie uns zunächst unsere JSON-Daten in Variablen vor der Funktion requestListener() speichern:

      first-servers/routes.js

      ...
      const books = JSON.stringify([
          { title: "The Alchemist", author: "Paulo Coelho", year: 1988 },
          { title: "The Prophet", author: "Kahlil Gibran", year: 1923 }
      ]);
      
      const authors = JSON.stringify([
          { name: "Paulo Coelho", countryOfBirth: "Brazil", yearOfBirth: 1947 },
          { name: "Kahlil Gibran", countryOfBirth: "Lebanon", yearOfBirth: 1883 }
      ]);
      ...
      

      Die Variable books ist eine Zeichenfolge, die JSON für eine Gruppe von Buchobjekten enthält. Jedes Buch hat einen Titel oder Namen, einen Autor und ein Veröffentlichungsjahr.

      Die Variable authors ist eine Zeichenfolge, die JSON für eine Reihe von Autorenobjekten enthält. Jeder Autor hat einen Namen, ein Geburtsland und ein Geburtsjahr.

      Nachdem wir nun über die Daten verfügen, die unsere Antworten zurückgeben werden, beginnen wir, die Funktion requestListener() zu ändern, um sie auf die richtigen Routen zurückzuleiten.

      Zuerst stellen wir sicher, dass jede Antwort von unserem Server den richtigen Content-Type-Header aufweist:

      first-servers/routes.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "application/json");
      }
      ...
      

      Jetzt möchten wir je nach URL-Pfad, den der Benutzer besucht, die richtige JSON zurückgeben. Lassen Sie uns eine switch-Anweisung zur URL der Anfrage erstellen:

      first-servers/routes.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "application/json");
          switch (req.url) {}
      }
      ...
      

      Um den URL-Pfad eines Anfrageobjekts zu erhalten, müssen wir auf seine url-Eigenschaft zugreifen. Wir können nun Fälle in die switch-Anweisung einfügen, um die entsprechende JSON zurückzugeben.

      Die switch-Anweisung von JavaScript bietet eine Möglichkeit zu steuern, welcher Code je nach Wert eines Objekts oder JavaScript-Ausdrucks (z. B. Ergebnis mathematischer Operationen) ausgeführt wird. Wenn Sie eine Lektion oder Erinnerung zu ihrer Verwendung benötigen, lesen Sie unseren Leitfaden Verwenden der switch-Anweisung in JavaScript.

      Lassen Sie uns einen case (Fall) für die Situation einfügen, dass der Benutzer unsere Liste von Büchern erhalten möchte:

      first-servers/routes.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "application/json");
          switch (req.url) {
              case "/books":
                  res.writeHead(200);
                  res.end(books);
                  break
          }
      }
      ...
      

      Wir setzen unseren Statuscode auf 200, um anzuzeigen, dass die Anfrage in Ordnung ist, und geben die JSON zurück, die die Liste unserer Bücher enthält. Lassen Sie uns nun einen weiteren case (Fall) für unsere Autoren einfügen:

      first-servers/routes.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "application/json");
          switch (req.url) {
              case "/books":
                  res.writeHead(200);
                  res.end(books);
                  break
              case "/authors":
                  res.writeHead(200);
                  res.end(authors);
                  break
          }
      }
      ...
      

      Wie zuvor wird der Statuscode 200 betragen, da die Anfrage in Ordnung ist. Dieses Mal geben wir die JSON zurück, die die Liste unserer Autoren enthält.

      Wir wollen einen Fehler zurückgeben, wenn der Benutzer einen beliebigen anderen Pfad aufrufen möchte. Lassen Sie uns dazu den Standardfall einfügen:

      routes.js

      ...
      const requestListener = function (req, res) {
          res.setHeader("Content-Type", "application/json");
          switch (req.url) {
              case "/books":
                  res.writeHead(200);
                  res.end(books);
                  break
              case "/authors":
                  res.writeHead(200);
                  res.end(authors);
                  break
              default:
                  res.writeHead(404);
                  res.end(JSON.stringify({error:"Resource not found"}));
          }
      }
      ...
      

      Wir verwenden das default-Stichwort in einer switch-Anweisung, um alle anderen Szenarien zu erfassen, die von unseren vorherigen Fällen nicht abgedeckt werden. Wir setzen den Statuscode auf 404, um anzuzeigen, dass die gewünschte URL nicht gefunden wurde. Dann legen wir ein JSON-Objekt fest, das eine Fehlermeldung enthält.

      Lassen Sie uns unseren Server testen, um zu sehen, ob er sich wie erwartet verhält. Führen wir in einem anderen Terminal zuerst einen Befehl aus, um zu sehen, ob wir unsere Liste mit Büchern erhalten:

      • curl http://localhost:8000/books

      Drücken Sie Enter, um die folgende Ausgabe zu sehen:

      Output

      [{"title":"The Alchemist","author":"Paulo Coelho","year":1988},{"title":"The Prophet","author":"Kahlil Gibran","year":1923}]

      Das funktioniert schon einmal gut. Lassen Sie uns das gleiche für /authors ausprobieren. Geben Sie den folgenden Befehl im Terminal ein:

      • curl http://localhost:8000/authors

      Sie sehen die folgende Ausgabe, sobald der Befehl abgeschlossen wurde:

      Output

      [{"name":"Paulo Coelho","countryOfBirth":"Brazil","yearOfBirth":1947},{"name":"Kahlil Gibran","countryOfBirth":"Lebanon","yearOfBirth":1883}]

      Lassen Sie uns zuletzt eine fehlerhafte URL ausprobieren, um sicherzustellen, dass requestListener() die Fehlerantwort zurückgibt:

      • curl http://localhost:8000/notreal

      Bei Eingabe dieses Befehls wird folgende Nachricht angezeigt:

      Output

      {"error":"Resource not found"}

      Sie können den laufenden Server mit Strg+C beenden.

      Wir haben nun verschiedene Wege für Benutzer erstellt, um verschiedene Daten zu erhalten. Wir haben auch eine Standardantwort hinzugefügt, die einen HTTP-Fehler zurückgibt, wenn der Benutzer eine URL eingibt, die wir nicht unterstützen.

      Zusammenfassung

      In diesem Tutorial haben Sie eine Reihe von Node.js-HTTP-Servern erstellt. Zuerst haben Sie eine einfache Textantwort zurückgegeben. Dann haben Sie von unserem Server verschiedene Arten von Daten zurückgegeben: JSON, CSV und HTML. Ab da konnten Sie das Laden von Dateien mit HTTP-Antworten kombinieren, um eine HTML-Seite vom Server an den Benutzer zurückzugeben, und eine API erstellen, die Informationen über die Anfrage des Benutzers verwendet, um zu bestimmen, welche Daten in der Antwort gesendet werden sollen.

      Sie sind nun dazu in der Lage, Webserver zu erstellen, die eine Vielzahl von Anfragen und Antworten bearbeiten können. Mit diesem Wissen können Sie einen Server einrichten, der an verschiedenen Endpunkten viele HTML-Seiten an den Benutzer zurückgibt. Außerdem können Sie Ihre eigene API erstellen.

      Um mehr über weitere HTTP-Webserver in Node.js zu erfahren, können Sie die Node.js-Dokumentation im http-Modul lesen. Wenn Sie noch mehr über Node.js erfahren möchten, können Sie zu der Serienseite Codieren in Node.js zurückkehren.



      Source link

      Erstellen von React-Elementen mit JSX


      Der Autor hat Creative Commons dazu ausgewählt, im Rahmen des Programms Write for DOnations eine Spende zu erhalten.

      Einführung

      In diesem Tutorial lernen Sie, wie Sie Elemente mit JSX beschreiben. JSX ist eine Abstraktion, die es Ihnen erlaubt, eine HTML-ähnliche Syntax in Ihren JavaScript-Code zu schreiben und ermöglicht es Ihnen, React-Komponenten zu erstellen, die wie Standard-HTML-Markup aussehen. JSX ist die Vorlagensprache der React-Elemente und bildet daher die Grundlage für jedes Markup, das React in Ihrer Anwendung rendert.

      Da Sie mit JSX auch JavaScript in Ihr Markup schreiben können, können Sie die Vorteile von JavaScript-Funktionen und -Methoden nutzen, einschließlich Array-Mapping und Kurzschlussevaluierung für Bedingungen.

      Im Rahmen des Tutorials werden Sie Klick-Ereignisse auf Schaltflächen direkt im Markup erfassen und Instanzen abfangen, wenn die Syntax nicht exakt mit Standard-HTML übereinstimmt, wie zum Beispiel bei CSS-Klassen. Am Ende dieses Tutorials haben Sie eine funktionierende Anwendung, die eine Vielzahl von JSX-Funktionen verwendet, um eine Liste von Elementen anzuzeigen, die über einen integrierten Klick-Listener verfügen. Dies ist ein übliches Muster in React-Anwendungen, das Sie während des Erlernens des Frameworks häufig verwenden werden. Sie werden auch in der Lage sein, Standard-HTML-Elemente mit JavaScript zu mischen und dabei sehen, wie React Ihnen ermöglicht, kleine, wiederverwendbare Code-Stücke zu erstellen.

      Voraussetzungen

      Schritt 1 — Hinzufügen eines Markups zu einem React-Element

      Wie bereits erwähnt, verfügt React über eine spezielle Markup-Sprache namens JSX. Diese vermischt HTML- und JavaScript-Syntax und sieht in etwa so aus:

      <div>
        {inventory.filter(item => item.available).map(item => (
          <Card>
              <div className="title"}>{item.name}</div>
              <div className="price">{item.price}</div>
          </Card>
          ))
        }
      </div>
      

      Sie werden einige JavaScript-Funktionalität wie .filter und .map sowie Standard-HTML wie <div> erkennen. Es gibt aber auch andere Teile, die wie HTML und JavaScript aussehen, wie <Card> und className.

      Dabei handelt es sich um JSX, die spezielle Markup-Sprache, die React-Komponenten den Anschein von HTML mit der Leistungsfähigkeit von JavaScript verleiht.

      In diesem Schritt lernen Sie, grundlegende HTML-ähnliche Syntax zu einem bestehenden React-Element hinzuzufügen. Zu Beginn fügen Sie Standard-HTML-Elemente in eine JavaScript-Funktion ein und sehen dann den kompilierten Code in einem Browser. Außerdem gruppieren Sie Elemente, damit React diese mit minimalem Markup kompilieren kann und dadurch eine klare HTML-Ausgabe hinterlässt.

      Beginnen Sie mit der Erstellung eines neuen Projekts. Führen Sie auf Ihrer Befehlszeile das folgende Skript aus, um ein neues Projekt mit create-react-app zu installieren:

      • npx create-react-app jsx-tutorial

      Nachdem das Projekt erstellt ist, wechseln Sie in das Verzeichnis:

      Starten Sie das Projekt in einer neuen Terminal-Registerkarte oder einem -fenster mit dem Create React App start-Skript. Der Browser aktualisiert Änderungen automatisch; lassen Sie also dieses Skript während der gesamten Dauer Ihrer Arbeit laufen:

      Sie erhalten einen funktionierenden lokalen Server. Falls sich das Projekt nicht in einem Browserfenster geöffnet hat, finden Sie es unter http://localhost:3000/. Wenn Sie dies von einem Remote-Server aus ausführen, ist die Adresse http://your_IP_address:3000.

      Ihr Browser wird mit einer React-Anwendung geladen, die als Teil von Create React App enthalten ist.

      React-Vorlagenprojekt

      Sie werden ein vollständig neues Set von benutzerdefinierten Komponenten erstellen, sodass Sie zunächst etwas Standardcode löschen müssen, um ein leeres Projekt zu erhalten. Zuerst öffnen Sie App.js in einem Texteditor. Das ist die Stammkomponente, die in der Seite injiziert wird. Alle Komponenten beginnen von hier.

      Gehen Sie in einem neuen Terminal in den Projektordner und öffnen Sie src/App.js mit dem folgenden Befehl:

      Sie sehen eine Datei wie diese:

      jsx-tutorial/src/App.js

      import React from 'react';
      import logo from './logo.svg';
      import './App.css';
      
      function App() {
        return (
          <div className="App">
            <header className="App-header">
              <img src={logo} className="App-logo" alt="logo" />
              <p>
                Edit <code>src/App.js</code> and save to reload.
              </p>
              <a
                className="App-link"
                href="https://reactjs.org"
                target="_blank"
                rel="noopener noreferrer"
              >
                Learn React
              </a>
            </header>
          </div>
        );
      }
      
      export default App;
      

      Löschen Sie nun die Zeile import logo from './logo.svg sowie alles nach der return-Anweisung in der Funktion. Ändern Sie diese zu return null. Der endgültige Code sieht so aus:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      function App() {
        return null;
      }
      
      export default App;
      

      Speichern und schließen Sie den Texteditor.

      Abschließend löschen Sie das Logo. Geben Sie im Terminalfenster den folgenden Befehl ein:

      Sie werden diese SVG-Datei nicht in Ihrer Anwendung verwenden und Sie sollten unbenutzte Dateien entfernen, während Sie arbeiten. So wird Ihr Code langfristig besser organisiert.

      Nachdem diese Teile Ihres Projekts nun entfernt sind, können Sie die Facetten von JSX erkunden. Diese Markup-Sprache wird von React kompiliert und wird schließlich zu dem HTML, das Sie auf einer Webseite sehen. Ohne zu sehr in die Einzelheiten zu gehen, nimmt React die JSX und erstellt ein Modell Ihrer zukünftigen Seite sowie anschließend die erforderlichen Elemente, die dann in Ihre Seite eingefügt werden.

      Das bedeutet, dass Sie etwas schreiben können, das wie HTML aussieht, und erwarten können, dass das gerenderte HTML ähnlich sein wird. Es gibt jedoch einige Fallstricke.

      Wenn Sie sich zunächst die Registerkarte oder das Fenster ansehen, auf dem Ihr Server läuft, sehen Sie Folgendes:

      Output

      ... ./src/App.js Line 1:8: 'React' is defined but never used no-unused-vars ...

      Das ist der Linter, der Ihnen sagt, dass Sie den importierten React-Code nicht verwenden. Wenn Sie die Zeile import React from 'react' in Ihren Code einfügen, importieren Sie JavaScript-Code, der die JSX in React-Code konvertiert. Wenn keine JSX vorhanden ist, ist das Importieren nicht erforderlich.

      Wir ändern dies, indem wir einen kleinen Teil JSX einfügen. Beginnen Sie, indem Sie null durch das Beispiel Hello, World ersetzen:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      function App() {
        return <h1>Hello, World</h1>;
      }
      
      export default App;
      

      Speichern Sie die Datei. Wenn Sie sich das Terminal mit dem laufenden Server ansehen, ist die Warnmeldung verschwunden. Wenn Sie Ihren Browser besuchen, sehen Sie die Nachricht als h1-Element.

      Bildschirmanzeige des Browsers mit „Hello, World“

      Fügen Sie als Nächstes unter dem Tag <h1> ein Absatz-Tag mit der Zeichenfolge I am writing JSX ein. Der Code sieht dann so aus:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      function App() {
        return(
          <h1>Hello, World</h1>
          <p>I am writing JSX</p>
        )
      }
      
      export default App;
      

      Da JSX mehrere Zeilen umfasst, müssen Sie den Ausdruck in Klammern setzten.

      Speichern Sie die Datei. Wenn Sie dies tun, sehen Sie einen Fehler in dem Terminal, auf dem Ihr Server läuft:

      Output

      ./src/App.js Line 7:5: Parsing error: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>? 5 | return( 6 | <h1>Hello, World</h1> > 7 | <p>I am writing JSX</p> | ^ 8 | ) 9 | } 10 |

      Wenn Sie JSX von einer Funktion oder Anweisung zurückgeben, müssen Sie ein einzelnes Element zurückgeben. Dieses Element kann verschachtelte Unterelemente haben, aber es muss ein einzelnes Element der obersten Ebene vorhanden sein. In diesem Fall geben Sie zwei Elemente zurück.

      Die Lösung ist eine kleine Codeänderung. Umgeben Sie den Code mit einem leeren Tag. Ein leeres Tag ist ein HTML-Element ohne Wörter. Es sieht so aus: <></>.

      Gehen Sie zu ./src/App.js in Ihrem Editor zurück und fügen Sie das leere Tag ein:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      function App() {
        return(
          <>
            <h1>Hello, World</h1>
            <p>I am writing JSX</p>
          </>
        )
      }
      
      export default App;
      

      Das leere Tag erstellt ein einzelnes Element, aber wenn der Code kompiliert wird, wird es nicht in das endgültige Markup eingefügt. Dadurch wird Ihr Code sauber gehalten und dennoch ein einzelnes Element an React gegeben.

      Anmerkung: Sie könnten den Code auch mit einem div anstatt eines leeren Tags umgeben, solange der Code ein Element zurückgibt. In diesem Beispiel hat ein leeres Tag den Vorteil, dass kein zusätzliches Markup in die gegliederte Ausgabe eingefügt wird.

      Speichern Sie den Code und schließen Sie die Datei. Ihr Browser aktualisiert sich und zeigt die aktualisierte Seite mit dem Absatz-Element an. Zusätzlich werden die leeren Tags bei der Konvertierung des Codes ausgelassen:

      Browser mit Anzeige des Markups und DevTools mit Anzeige des Markups ohne leere Tags

      Sie haben nun einige grundlegende JSX in Ihre Komponente eingefügt und gelernt, wie die gesamte JSX in einer einzelnen Komponente geschachtelt werden muss. Im nächsten Schritt geben Sie Ihre Komponente ein Styling.

      Schritt 2 — Hinzufügen eines Stylings zu einem Element mit Attributen

      In diesem Schritt stylen Sie die Elemente in Ihrer Komponente, um zu lernen, wie HTML-Attribute mit JSX arbeiten. Es gibt zahlreiche Styling-Optionen in React. Einige von ihnen erfordern das Schreiben von CSS in Javascript, andere verwenden Präprozessoren. In diesem Tutorial arbeiten Sie mit importierten CSS und CSS-Klassen.

      Sie haben nun Ihren Code und können diesem nun ein Styling hinzufügen. Öffnen Sie App.css in Ihrem Texteditor:

      Da Sie mit neuer JSX beginnen, bezieht sich das aktuelle CSS auf Elemente, die nicht mehr existieren. Da Sie kein CSS benötigen, können Sie es löschen.

      Nach der Löschung des Codes haben Sie eine leere Datei.

      Als Nächstes fügen Sie ein Styling hinzu, um den Text zu zentrieren. Fügen Sie den folgenden Code in src/App.css ein:

      jsx-tutorial/src/App.css

      .container {
          display: flex;
          flex-direction: column;
          align-items: center;
      }
      

      In diesem Codeblock haben Sie einen CSS-Klassenselektor namens .container erstellt und dazu verwendet, den Inhalt mit display:flex zu zentrieren.

      Speichern Sie die Datei und schließen Sie sie. Der Browser wird aktualisiert, aber es wird sich nichts ändern. Bevor Sie die Änderung sehen können, müssen Sie die CSS-Klasse zu Ihrer React-Komponente hinzufügen. Öffnen Sie den JavaScript-Code der Komponente:

      Der CSS-Code wurde bereits mit der Zeile import './App.css' importiert. Das bedeutet, dass webpack den Code einzieht, um ein endgültiges Stylesheet zu erstellen, aber um das CSS auf Ihre Elemente anzuwenden, müssen Sie die Klassen hinzufügen.

      Ändern Sie zuerst in Ihrem Texteditor die leeren Tags, <>, in <div>.

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      function App() {
        return(
          <div>
            <h1>Hello, World</h1>
            <p>I am writing JSX</p>
          </div>
        )
      }
      
      export default App;
      

      In diesem Code haben Sie die leeren Tags — <> — mit div-Tags ersetzt. Leere Tags sind nützlich, um Ihren Code zu gruppieren, ohne zusätzliche Tags einzufügen, aber hier müssen Sie ein div verwenden, da leere Tags keine HTML-Attribute akzeptieren.

      Als Nächstes müssen Sie den Klassennamen hinzufügen. Hier beginnt JSX, von HTML abzuweichen. Wenn Sie eine Klasse zu einem gängigen HTML-Element hinzufügen wollten, würden Sie das so tun:

      <div class="container">
      

      Da JSX jedoch JavaScript ist, hat es einige Beschränkungen. Eine der Beschränkungen besteht darin, dass JavaScript reservierte Schlüsselwörter hat. Das bedeutet, dass Sie bestimmte Wörter in keinem JavaScript-Code verwenden können. Sie können zum Beispiel keine Variable mit der Bezeichnung null erstellen, da dieses Wort bereits reserviert ist.

      Eines der reservierten Wörter ist class. React umgeht dieses reservierte Wort, indem es leicht geändert wird. Anstelle des Attributs class fügen Sie das Attribut className hinzu. Wenn ein Attribut nicht wie erwartet funktioniert, können Sie generell versuchen, die Version mit einer Binnenmajuskel hinzufügen. Ein weiteres Attribut, das leicht abweicht, ist das Attribut for, das Sie für Labels verwenden würden. Es gibt einige weitere Fälle, aber glücklicherweise ist die Liste ziemlich kurz.

      Anmerkung: In React werden Attribute oft props genannt. Props sind Datenstücke, die Sie an andere benutzerdefinierte Komponenten übergeben können. Sie sehen so aus wie Attribute, außer dass sie keinen HTML-Spezifikationen entsprechen. In diesem Tutorial nennen wir sie Attribute, da sie hauptsächlich wie Standard-HTML-Attribute verwendet werden. Das unterscheidet sie von den Props, die sich nicht wie HTML-Attribute verhalten, was später in dieser Serie behandelt wird.

      Nachdem Sie nun wissen, wie das Attribut class in React verwendet wird, können Sie Ihren Code aktualisieren, um das Styling einzubeziehen. Fügen Sie in Ihrem Texteditor className="container" in Ihr öffnendes div-Tag ein:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      function App() {
        return(
          <div className="container">
            <h1>Hello, World</h1>
            <p>I am writing JSX</p>
          </div>
        )
      }
      
      export default App;
      

      Speichern Sie die Datei. Wenn Sie dies tun, wird die Seite neu geladen und der Inhalt wird zentriert.

      Zentrierte HTML-Elemente in einem Browser.

      Das Attribut className ist in React einzigartig. Sie können die meisten HTML-Attribute ohne Änderung in JSX einfügen. Gehen Sie als Beispiel zurück in Ihren Texteditor und fügen Sie Ihrem <h1>-Element eine id von greeting hinzu. Es wird aussehen wie Standard-HTML:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      function App() {
        return(
          <div className="container">
            <h1 id="greeting">Hello, World</h1>
            <p>I am writing JSX</p>
          </div>
        )
      }
      
      export default App;
      

      Speichern Sie die Seite und laden Sie den Browser neu. Sie wird gleich bleiben.

      Bis hierher sieht JSX wie Standard-Markup aus. Aber der Vorteil von JSX ist, dass es, obwohl es wie HTML aussieht, die Leistungsfähigkeit von JavaScript hat. Das bedeutet, dass Sie Variablen zuweisen und in Ihren Attributen referenzieren können. Um ein Attribut zu referenzieren, umschließen Sie es mit geschweiften Klammern — {} — anstelle von Anführungszeichen.

      Fügen Sie in Ihrem Texteditor die folgenden hervorgehobenen Zeilen ein, um ein Attribut zu referenzieren:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      function App() {
        const greeting = "greeting";
        return(
          <div className="container">
           <h1 id={greeting}>Hello, World</h1>
            <p>I am writing JSX</p>
          </div>
        )
      }
      
      export default App;
      

      In diesem Code haben Sie eine Variable über der return-Anweisung namens greeting mit dem Wert von "greeting" erstellt und dann die Variable im Attribut id Ihres <h1>-Tags referenziert.

      Speichern und schließen Sie die Datei. Die Seite wird gleich sein, hat aber ein id-Tag.

      Seite mit hervorgehobenem id-Tag in den Entwickler-Tools

      Bisher haben Sie mit einigen wenigen Elementen einzeln gearbeitet, aber Sie können JSX auch verwenden, um viele HTML-Elemente zur Erstellung komplexer Seiten hinzuzufügen und zu verschachteln.

      Um dies zu demonstrieren, erstellen Sie eine Seite mit einer Liste von Emojis. Diese Emojis werden von einem <button>-Element umgeben. Wenn Sie auf das Emoji klicken, erhalten Sie dessen CLDR-Kurznamen.

      Zu Beginn müssen Sie einige weitere Elemente in die Seite einfügen. Öffnen Sie src/App.js in Ihrem Texteditor. Lassen Sie ihn während dieses Schritts geöffnet.

      Fügen Sie zunächst eine Liste von Emojis hinzu, indem Sie die folgenden hervorgehobenen Zeilen einfügen:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      function App() {
        const greeting = "greeting";
        return(
          <div className="container">
            <h1 id={greeting}>Hello, World</h1>
            <p>I am writing JSX</p>
            <ul>
              <li>
                  <button>
                    <span role="img" aria-label="grinning face" id="grinning face">😀</span>
                  </button>
              </li>
              <li>
                <button>
                    <span role="img" aria-label="party popper" id="party popper">🎉</span>
                </button>
              </li>
              <li>
                <button>
                    <span role="img" aria-label="woman dancing" id="woman dancing">💃</span>
                </button>
              </li>
            </ul>
          </div>
        )
      }
      
      export default App;
      

      Sie haben hier ein <ul>-Tag erstellt, um eine Liste von Emojis zu umfassen. Jedes Emoji ist in einem separaten <li>-Element und von einem <button>-Element umgeben. Im nächsten Schritt fügen Sie diesem Button ein Ereignis hinzu.

      Zudem haben Sie das Emoji mit einem <span>-Tag umgeben, das einige weitere Attribute hat. Jedes span hat das Attribut role, das auf die Rolle img gesetzt ist. Dadurch wird barrierefreier Software signalisiert, dass sich das Element wie ein Bild verhält. Außerdem verfügt jedes <span> auch über ein aria-label und ein id-Attribut mit dem Namen des Emojis. Das aria-label sagt Besuchern mit Bildschirmlesern, was angezeigt wird. Beim Schreiben von Ereignissen im nächsten Schritt verwenden Sie die id.

      Wenn Sie auf diese Weise Code schreiben, verwenden Sie semantische Elemente, die dazu beitragen, dass die Seite barrierefrei und verständlich für Bildschirmleser ist.

      Speichern und schließen Sie die Datei. Ihr Browser wird aktualisiert und Sie sehen Folgendes:

      Browser mit Emojis im Stil einer Liste

      Fügen Sie nun etwas Styling hinzu. Öffnen Sie den CSS-Code in Ihrem Texteditor:

      Fügen Sie den folgenden hervorgehobenen Code hinzu, um den Standard-Hintergrund und die Ränder der Buttons zu entfernen und um die Schriftgröße zu erhöhen:

      jsx-tutorial/src/App.css

      .container {
          display: flex;
          flex-direction: column;
          align-items: center;
      }
      
      button {
          font-size: 2em;
          border: 0;
          padding: 0;
          background: none;
          cursor: pointer;
      }
      
      ul {
          display: flex;
          padding: 0;
      }
      
      li {
          margin: 0 20px;
          list-style: none;
          padding: 0;
      }
      

      In diesem Code haben Sie font-size, border und andere Parameter verwendet, um das Aussehen Ihrer Buttons anzupassen und die Schriftart zu ändern. Sie haben auch den Listenstil entfernt und display:flex in das <ul>-Element eingefügt, um eine horizontale Ausführung zu erhalten.

      Speichern und schließen Sie die CSS-Datei. Ihr Browser wird aktualisiert und Sie sehen Folgendes:

      Liste mit Standardstilen entfernt

      Sie haben nun mit mehreren JSX-Elementen gearbeitet, die wie reguläres HTML aussehen. Sie haben Klassen, IDs und aria-Tags eingefügt sowie mit Daten als Zeichenfolgen und Variablen gearbeitet. React verwendet aber auch Attribute, um zu definieren, wie Ihre Elemente auf Benutzerereignisse reagieren sollen. Im nächsten Schritt beginnen Sie, die Seite interaktiver zu machen, indem Sie dem Button Ereignisse hinzufügen.

      Schritt 3 — Hinzufügen von Ereignissen zu Elemente

      In diesem Schritt fügen Sie mit speziellen Attributen Ereignisse zu Elementen hinzu und erfassen ein Klick-Ereignis auf einem Button-Element. Sie lernen, wie Sie Informationen von dem Ereignis erfassen, um eine andere Aktion zu senden oder andere Informationen im Rahmen der Datei zu verwenden.

      Sie haben nun eine grundlegende Seite mit Informationen und können nun einige Ereignisse zu diesen hinzufügen. Es gibt zahlreiche Event-Handler, die Sie zu HTML-Elementen hinzufügen können. Mit React können Sie auf all diese zugreifen. Da Ihr JavaScript-Code mit Ihrem Markup gekoppelt ist, können Sie die Ereignisse schnell einfügen und gleichzeitig Ihren Code gut organisiert halten.

      Zunächst fügen Sie den Event Handler onclick hinzu. Dadurch können Sie einen JavaScript-Code direkt in Ihr Element einfügen, anstatt einen Event-Listener anzufügen:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      function App() {
        const greeting = "greeting";
        return(
          <div className="container">
            <h1 id={greeting}>Hello, World</h1>
            <p>I am writing JSX</p>
            <ul>
              <li>
                <button
                  onClick={event => alert(event.target.id)}
                >
                  <span role="img" aria-label="grinning face" id="grinning face">😀</span>
                </button>
              </li>
              <li>
                <button
                  onClick={event => alert(event.target.id)}
                >
                    <span role="img" aria-label="party popper" id="party popper">🎉</span>
                </button>
              </li>
              <li>
                  <button
                    onClick={event => alert(event.target.id)}
                  >
                    <span role="img" aria-label="woman dancing" id="woman dancing">💃</span>
                </button>
              </li>
            </ul>
          </div>
        )
      }
      
      export default App;
      

      Da es sich um JSX handelt, haben Sie onclick mit einer Binnenmajuskel versehen, d. h. Sie haben es als onClick eingefügt. Das Attribut onClick verwendet eine anonyme Funktion, um Informationen über das Element abzurufen, das angeklickt wurde.

      Sie haben eine anonyme Pfeilfunktion hinzugefügt, die das Ereignis von dem angeklickten Button abruft. Das Ereignis wird als Ziel das <span>-Element haben. Die Information, die Sie benötigen, ist im id-Attribut, auf das Sie mit event.target.id zugreifen können. Sie können den Hinweis mit der Funktion alert() auslösen.

      Speichern Sie die Datei. Klicken Sie in Ihrem Browser auf ein Emoji und Sie erhalten einen Hinweis mit dem Namen.

      Hinweis für Party Popper

      Sie können Wiederholungen reduzieren, indem Sie die Funktion einmal deklarieren und sie an jede onClick-Aktion übergeben. Da die Funktion nur auf Ein- und Ausgaben angewiesen ist, können Sie sie außerhalb der Hauptkomponentenfunktion deklarieren. Mit anderen Worten, die Funktion muss nicht auf den Anwendungsbereich der Komponente zugreifen. Der Vorteil einer Auseinanderhaltung besteht darin, dass Ihre Komponentenfunktion etwas kürzer ist und Sie die Funktion später in eine separate Datei verschieben können, wenn Sie möchten.

      Erstellen Sie in Ihrem Texteditor eine Funktion namens displayEmojiName, die das Ereignis nimmt und die Funktion alert() mit einer ID aufruft. Dann übergeben Sie die Funktion an jedes onClick-Attribut:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      const displayEmojiName = event => alert(event.target.id);
      
      function App() {
        const greeting = "greeting";
        return(
          <div className="container">
            <h1 id={greeting}>Hello, World</h1>
            <p>I am writing JSX</p>
            <ul>
              <li>
                <button
                  onClick={displayEmojiName}
                >
                  <span role="img" aria-label="grinning face" id="grinning face">😀</span>
                </button>
              </li>
              <li>
                <button
                  onClick={displayEmojiName}
                >
                    <span role="img" aria-label="party popper" id="party popper">🎉</span>
                </button>
              </li>
              <li>
                  <button
                    onClick={displayEmojiName}
                  >
                    <span role="img" aria-label="woman dancing" id="woman dancing">💃</span>
                </button>
              </li>
            </ul>
          </div>
        )
      }
      
      export default App;
      

      Speichern Sie die Datei. Klicken Sie in Ihrem Browser auf ein Emoji und Sie werden den gleichen Hinweis sehen.

      In diesem Schritt haben Sie jedem Element Ereignisse hinzugefügt. Sie haben auch gesehen, wie JSX leicht abweichende Namen für Elementereignisse verwendet und begonnen, wiederverwendbaren Code zu schreiben, indem Sie die Funktion genommen und in mehreren Elementen erneut verwendet haben. Im nächsten Schritt schreiben Sie eine wiederverwendbare Funktion, die JSX-Elemente ausgibt, anstatt jedes Element per Hand zu schreiben. Dadurch werden Wiederholungen noch weiter reduziert.

      Schritt 4 — Mapping von Daten zur Erstellung von Elementen

      In diesem Schritt gehen Sie über die Verwendung von JSX als einfaches Markup hinaus. Sie lernen, es mit JavaScript zu kombinieren, um dynamisches Markup zu erstellen, das Code reduziert und die Lesbarkeit verbessert. Sie gestalten Ihren Code in ein Array um, über das Sie eine Schleife ausführen, um HTML-Elemente zu erstellen.

      JSX beschränkt Sie nicht auf eine HTML-ähnliche Syntax. Es bietet Ihnen auch die Möglichkeit, JavaScript direkt in Ihrem Markup zu verwenden. Das haben Sie bereits ausprobiert, indem Sie Funktionen an Attribute übergeben haben. Sie haben auch Variablen zur Wiederverwendung von Daten verwendet. Nun können Sie JSX direkt aus Daten unter Verwendung von Standard-JavaScript-Code erstellen.

      Sie müssen in Ihrem Texteditor ein Array der Emoji-Daten in der Datei src/App.js erstellen. Öffnen Sie die Datei, falls Sie diese geschlossen haben:

      Fügen Sie ein Array ein, das Objekte enthält, die das Emoji und den Namen des Emojis beinhalten. Beachten Sie, dass Emojis von Anführungszeichen umgeben sein müssen. Erstellen Sie dieses Array über der App-Funktion:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      const displayEmojiName = event => alert(event.target.id);
      const emojis = [
        {
          emoji: "😀",
          name: "grinning face"
        },
        {
          emoji: "🎉",
          name: "party popper"
        },
        {
          emoji: "💃",
          name: "woman dancing"
        }
      ];
      
      function App() {
      ...
      }
      
      export default App;
      

      Nachdem Sie nun über die Daten verfügen, können Sie eine Schleife über diese ausführen. Um JavaScript innerhalb von JSX zu verwenden, müssen Sie es mit geschweiften Klammern umschließen: {}. Es ist das Gleiche wie bei den Funktionen, die Sie in Attribute eingefügt haben.

      Um React-Komponenten zu erstellen, müssen Sie die Daten in JSX-Elemente konvertieren. Dazu führen Sie ein Mapping der Daten aus und geben ein JSX-Element aus. Es gibt ein paar Dinge, die Sie beim Schreiben des Codes beachten müssen.

      Erstens muss eine Gruppe von Elementen von einem <div>-Container umgeben sein. Zweitens benötigt jedes Element eine spezielle Eigenschaft namens key – Schlüssel. Der key muss ein eindeutiges Datenstück sein. Mit diesem kann React die Elemente verfolgen und dadurch erfahren, wann die Komponente aktualisiert werden muss. Der Schlüssel wird aus dem kompilierten HTML ausgelassen, da er nur internen Zwecken dient. Wann immer Sie mit Schleifen arbeiten, müssen Sie eine einfache Zeichenfolge als Schlüssel einfügen.

      Hier ist ein vereinfachtes Beispiel, das eine Liste von Namen auf ein enthaltendes <div> abbildet:

      ...
      const names = [
          "Atul Gawande",
          "Stan Sakai",
          "Barry Lopez"
      ];
      
      return(
          <div>
              {names.map(name => <div key={name}>{name}</div>)}
          </div>
      )
      ...
      

      Das resultierende HTML würde so aussehen:

      ...
      <div>
          <div>Atul Gawande</div>
          <div>Stan Sakai</div>
          <div>Barry Lopez</div>
      </div>
      ...
      

      Die Konvertierung der Emoji-Liste ist ähnlich. Das <ul> ist der Container. Sie führen ein Mapping von Daten aus und geben ein <li> mit einem Schlüssel des Kurznamens des Emojis aus. Sie ersetzen die hartcodierten Daten in den Tags <button> und <span> durch Informationen aus der Schleife.

      Fügen Sie Folgendes in Ihrem Texteditor ein:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      const displayEmojiName = event => alert(event.target.id);
      const emojis = [
        {
          emoji: '😀',
          name: "test grinning face"
        },
        {
          emoji: '🎉',
          name: "party popper"
        },
        {
          emoji: '💃',
          name: "woman dancing"
        }
      ];
      
      function App() {
        const greeting = "greeting";
        return(
          <div className="container">
            <h1 id={greeting}>Hello, World</h1>
            <p>I am writing JSX</p>
            <ul>
              {
                emojis.map(emoji => (
                  <li key={emoji.name}>
                    <button
                      onClick={displayEmojiName}
                    >
                      <span role="img" aria-label={emoji.name} id={emoji.name}>{emoji.emoji}</span>
                    </button>
                  </li>
                ))
              }
            </ul>
          </div>
        )
      }
      
      export default App;
      

      Im Code haben Sie über das emojis-Array im <ul>-Tag gemappt und ein <li> ausgegeben. In jedem <li> haben Sie den Namen des Emojis als key-Prop verwendet. Der Button wird die gleiche Funktion wie normalerweise haben. Ersetzen Sie im Element <span> das aria-label und id mit dem name. Der Inhalt des <span>-Tags sollte das Emoji sein.

      Speichern Sie die Datei. Ihr Fenster wird aktualisiert und Sie sehen die Daten. Beachten Sie, dass der Schlüssel nicht in dem generierten HTML vorhanden ist.

      Browser mit Entwickler-Tools, die das aktualisierte HTML ohne key-Props zeigen

      Das Kombinieren von JSX mit Standard JavaScript bietet Ihnen eine Menge Werkzeuge, um Inhalte dynamisch zu erstellen, und Sie können jedes gewünschte Standard-JavaScript verwenden. In diesem Schritt haben Sie hartkodiertes JSX durch ein Array und eine Schleife ersetzt, um HTML dynamisch zu erstellen. Im nächsten Schritt zeigen Sie Informationen bedingt an, indem Sie die Kurzschlussevaluierung anwenden.

      Schritt 5 — Bedingtes Anzeigen von Elementen mit Kurzschlussevaluierung

      In diesem Schritt verwenden Sie die Kurzschlussevaluierung, um bestimmte HTML-Elemente unter bestimmten Bedingungen anzuzeigen. Auf diese Weise können Sie Komponenten erstellen, die HTML auf der Grundlage zusätzlicher Informationen aus- oder einblenden können, wodurch Ihre Komponenten flexibel auf verschiedene Situationen reagieren können.

      In einigen Situationen kann es notwendig sein, dass eine Komponente Informationen in bestimmten Fällen anzeigt und in anderen nicht. Beispielsweise möchten Sie vielleicht nur dann eine Hinweismeldung für den Benutzer anzeigen, wenn bestimmte Fälle zutreffen, oder Sie möchten eventuell einige Account-Informationen für einen Admin anzeigen, die ein normaler Benutzer nicht sehen soll.

      Dazu verwenden Sie die Kurzschlussevaluierung. Das bedeutet, dass Sie eine Bedingung verwenden, und wenn der erste Teil zutrifft, werden die Informationen im zweiten Teil ausgegeben.

      Hier folgt ein Beispiel. Wenn Sie nur dann einen Button anzeigen wollen, wenn der Benutzer eingeloggt ist, umschließen Sie das Element mit geschweiften Klammern und fügen die Bedingung davor ein.

      {isLoggedIn && <button>Log Out</button>}
      

      In diesem Beispiel verwenden Sie den &&-Operator, der den letzten Wert ausgibt, wenn alles zutrifft. Andernfalls gibt es false aus, was React anweist, kein zusätzliches Markup auszugeben. Wenn isLoggedIn zutrifft ist, zeigt React den Button. Wenn isLoggedIn nicht zutrifft, wird der Button nicht angezeit.

      Fügen Sie zum Ausprobieren die folgenden hervorgehobenen Zeilen ein:

      jsx-tutorial/src/App.js

      import React from 'react';
      import './App.css';
      
      ...
      
      function App() {
        const greeting = "greeting";
        const displayAction = false;
        return(
          <div className="container">
            <h1 id={greeting}>Hello, World</h1>
            {displayAction && <p>I am writing JSX</p>}
            <ul>
      ...
            </ul>
          </div>
        )
      }
      
      export default App;
      

      Sie haben in Ihrem Texteditor eine Variable namens displayAction mit einem Wert von false erstellt. Dann haben Sie das <p>-Tag mit geschweiften Klammern umschlossen. Am Anfang der geschweiften Klammern haben Sie displayAction && eingefügt, um die Bedingung zu erstellen.

      Speichern Sie die Datei und Sie sehen, dass das Element in Ihrem Browser verschwindet. Wichtig ist auch, dass es auch nicht in dem generierten HTML erscheint. Dies ist nicht dasselbe wie das Ausblenden eines Elements mit CSS. Es wird im endgültigen Markup überhaupt nicht vorhanden sein.

      Browser mit Entwickler-Tools, die kein Paragrafenelement anzeigen

      Im Moment ist der Wert von displayAction hartkodiert, aber Sie können diesen Wert auch als einen State speichern oder als Prop aus einer übergeordneten Komponente übergeben.

      In diesem Schritt haben Sie gelernt, wie man bedingt Elemente anzeigt. Dadurch können Sie Komponenten erstellen, die auf der Grundlage anderer Informationen anpassbar sind.

      Zusammenfassung

      Bis hierher haben Sie eine benutzerdefinierte Anwendung mit JSX erstellt. Sie haben gelernt, wie man HTML-ähnliche Elemente in Ihre Komponente einfügt, diesen Elementen ein Styling gibt, Attribute übergibt, um semantisches und barrierefreies Markup zu erstellen, und Events in die Komponenten eingefügt. Dann haben Sie JavaScript in Ihr JSX gemischt, um Wiederholungen im Code zu verringern und um Elemente bedingt ein- und auszublenden.

      Das ist die Grundlage, die Sie benötigen, um zukünftige Komponenten zu erstellen. Mit einer Kombination aus JavaScript und HTML können Sie dynamische Komponenten erstellen, die flexibel sind und es Ihrer Anwendung ermöglichen, zu wachsen und sich zu verändern.

      Wenn Sie mehr über React erfahren möchten, besuchen Sie unsere Themenseite React.



      Source link

      Erstellen eines Hashicorp-Vault-Servers mit Packer und Terraform in DigitalOcean [Schnellstart]


      Einführung

      Vault von Hashicorp ist ein Open-Source-Tool, um Geheimnisse und sensible Daten in dynamischen Cloud-Umgebungen sicher zu speichern. Packer und Terraform, ebenfalls von Hashicorp entwickelt, können zusammen verwendet werden, um Images von Vault zu kreieren und bereitzustellen.

      In diesem Tutorial erstellen Sie mit Packer einen unveränderlichen Snapshot des Systems mit installiertem Vault und dirigieren dessen Bereitstellung mit Terraform.

      Eine ausführlichere Version dieses Tutorials finden Sie in Erstellen eines Hashicorp Vault-Servers mit Packer und Terraform in DigitalOcean.

      Voraussetzungen

      • Auf Ihrem lokalen Rechner installierter Packer. Lesen Sie für Anweisungen die offizielle Dokumentation.
      • Auf Ihrem lokalen Rechner installiertes Terraform. Lesen Sie die offizielle Dokumentation für eine Anleitung.
      • Ein persönliches Zugriffstoken (API-Schlüssel) mit Lese- und Schreibberechtigungen für Ihr DigitalOcean-Konto. Besuchen Sie Erstellen eines persönlichen Zugriffstokens, um ein Token zu erstellen.
      • Einen SSH-Schlüssel, den Sie zur Authentifizierung mit den bereitgestellten Vault Droplets verwenden, die auf Ihrem lokalen Rechner verfügbar sind und Ihrem DigitalOcean-Konto hinzugefügt werden. Sie benötigen auch dessen Fingerabdruck, den Sie von der Security-Seite Ihres Kontos nach dem Erstellen kopieren können. Besuchen Sie die DigitalOcean-Dokumentation für detaillierte Anweisungen oder das Tutorial Einrichten von SSH-Schlüsseln.

      Schritt 1 — Erstellen einer Packer-Vorlage

      Erstellen und wechseln Sie in das Verzeichnis ~/vault-orchestration, um Ihre Vault-Dateien zu speichern:

      • mkdir ~/vault-orchestration
      • cd ~/vault-orchestration

      Erstellen Sie separate Verzeichnisse für die Packer- und Terraform-Konfiguration, indem Sie Folgendes ausführen:

      Navigieren Sie zum Verzeichnis Packer:

      Verwenden von Vorlagenvariablen

      Erstellen Sie eine variables.json in Ihrem packer-Unterverzeichnis, um Ihre privaten variablen Daten zu speichern:

      Fügen Sie die folgenden Zeilen hinzu:

      ~/vault-orchestration/packer/variables.json

      {
        "do_token": "your_do_api_key",
        "base_system_image": "ubuntu-18-04-x64",
        "region": "nyc3",
        "size": "s-1vcpu-1gb"
      }
      

      Sie verwenden diese Variablen in der Vorlage, die Sie erstellen. Sie können die Werte Basisbild, Region und Droplet-Größe entsprechend den developer docs bearbeiten.

      Ersetzen Sie your_do_api_key durch Ihren API-Schlüssel. Speichern und schließen Sie dann die Datei.

      Erstellen von Builders und Provisioners

      Erstellen Sie Ihre Packer-Vorlage für Vault in einer Datei namens template.json:

      Fügen Sie die folgenden Zeilen hinzu:

      ~/vault-orchestration/packer/template.json

      {
         "builders": [{
             "type": "digitalocean",
             "api_token": "{{user `do_token`}}",
             "image": "{{user `base_system_image`}}",
             "region": "{{user `region`}}",
             "size": "{{user `size`}}",
             "ssh_username": "root"
         }],
         "provisioners": [{
             "type": "shell",
             "inline": [
                 "sleep 30",
                 "sudo apt-get update",
                 "sudo apt-get install unzip -y",
                 "curl -L https://releases.hashicorp.com/vault/1.3.2/vault_1.3.2_linux_amd64.zip -o vault.zip",
                 "unzip vault.zip",
                 "sudo chown root:root vault",
                 "mv vault /usr/local/bin/",
                 "rm -f vault.zip"
             ]
      }]
      }
      

      Sie definieren einen einfachen digitalocean-Builder. Packer erstellt ein temporäres Droplet der definierten Größe, des definierten Bilds und der definierten Region, wobei der bereitgestellte API-Schlüssel verwendet wird.

      Der Provisioner stellt über SSH eine Verbindung mit dem angegebenen Benutzernamen her und führt nacheinander alle definierten Provisioners aus, bevor ein DigitalOcean-Snapshot aus dem Droplet erstellt und gelöscht wird.

      Es ist eine Art Shell, die die angegebenen Befehle auf das Ziel ausführt. Die Befehle in der Vorlage warten 30 Sekunden, bis das System hochgefahren ist. Anschließend wird Vault 1.3.2 heruntergeladen und entpackt. Konsultieren Sie die offizielle Vault-Downloadseite, um die aktuellste Version für Linux zu erhalten.

      Speichern und schließen Sie die Datei.

      Überprüfen Sie die Gültigkeit Ihrer Vorlage:

      • packer validate -var-file=variables.json template.json

      Sie sehen die folgende Ausgabe:

      Output

      Template validated successfully.

      Schritt 2 — Erstellen des Snapshots

      Erstellen Sie Ihren Snapshot mit dem Packer-Befehl build:

      • packer build -var-file=variables.json template.json

      Sie sehen eine Menge Ausgabe, die so aussehen wird:

      Output

      digitalocean: output will be in this color. ==> digitalocean: Creating temporary ssh key for droplet... ==> digitalocean: Creating droplet... ==> digitalocean: Waiting for droplet to become active... ==> digitalocean: Using ssh communicator to connect: ... ==> digitalocean: Waiting for SSH to become available... ==> digitalocean: Connected to SSH! ==> digitalocean: Provisioning with shell script: /tmp/packer-shell035430322 ... ==> digitalocean: % Total % Received % Xferd Average Speed Time Time Time Current ==> digitalocean: Dload Upload Total Spent Left Speed digitalocean: Archive: vault.zip ==> digitalocean: 100 45.5M 100 45.5M 0 0 154M 0 --:--:-- --:--:-- --:--:-- 153M digitalocean: inflating: vault ==> digitalocean: Gracefully shutting down droplet... ==> digitalocean: Creating snapshot: packer-1581537927 ==> digitalocean: Waiting for snapshot to complete... ==> digitalocean: Destroying droplet... ==> digitalocean: Deleting temporary ssh key... Build 'digitalocean' finished. ==> Builds finished. The artifacts of successful builds are: --> digitalocean: A snapshot was created: 'packer-1581537927' (ID: 58230938) in regions '...'

      Die letzte Zeile enthält den Namen des Snapshots (wie packer-1581537927) und seine ID in Klammern, wie hier hervorgehoben. Notieren Sie sich die ID des Snapshots, da Sie diese im nächsten Schritt benötigen.

      Falls der Build-Prozess durch Fehler in der API fehlschlägt, warten Sie einige Minuten und versuchen Sie es dann erneut.

      Schritt 3 — Schreiben der Terraform-Konfiguration

      Navigieren Sie zum Unterverzeichnis terraform:

      • cd ~/vault-orchestration/terraform

      Erstellen Sie eine Datei namens do-provider.tf, um den Provider zu speichern:

      Fügen Sie die folgenden Zeilen hinzu:

      ~/vault-orchestration/terraform/do-provider.tf

      variable "do_token" {
      }
      
      variable "ssh_fingerprint" {
      }
      
      variable "instance_count" {
      default = "1"
      }
      
      variable "do_snapshot_id" {
      }
      
      variable "do_name" {
      default = "vault"
      }
      
      variable "do_region" {
      }
      
      variable "do_size" {
      }
      
      variable "do_private_networking" {
      default = true
      }
      
      provider "digitalocean" {
      token = var.do_token
      }
      

      Diese Datei stellt dem digitalocean-Provider einen API-Schlüssel zur Verfügung. Um die Werte dieser Variablen anzugeben, erstellen Sie eine Variablendefinitionsdatei, ähnlich wie bei Packer. Der Dateiname muss entweder auf .tfvars oder auf .tfvars.json enden.

      Speichern und schließen Sie die Datei.

      Erstellen Sie eine Variablendefinitionsdatei:

      Fügen Sie die folgenden Zeilen hinzu:

      ~/vault-orchestration/terraform/definitions.tf

      do_token         = "your_do_api_key"
      ssh_fingerprint  = "your_ssh_key_fingerprint"
      do_snapshot_id   = your_do_snapshot_id
      do_name          = "vault"
      do_region        = "nyc3"
      do_size          = "s-1vcpu-1gb"
      instance_count   = 1
      

      Ersetzen Sie your_do_api_key, your_ssh_key_fingerprint und your_do_snapshot_id (die Snapshot-ID, die Sie im vorherigen Schritt notiert haben). Die Parameter do_region und do_size müssen die gleichen Werte wie in der Packer-Variablendatei haben.

      Speichern und schließen Sie die Datei.

      Erstellen Sie die folgende Datei, um die Bereitstellungskonfiguration des Vault-Snapshots zu speichern:

      Fügen Sie die folgenden Zeilen hinzu:

      ~/vault-orchestration/terraform/deployment.tf

      resource "digitalocean_droplet" "vault" {
      count              = var.instance_count
      image              = var.do_snapshot_id
      name               = var.do_name
      region             = var.do_region
      size               = var.do_size
      private_networking = var.do_private_networking
      ssh_keys = [
        var.ssh_fingerprint
      ]
      }
      
      output "instance_ip_addr" {
      value = {
        for instance in digitalocean_droplet.vault:
        instance.id => instance.ipv4_address
      }
      description = "The IP addresses of the deployed instances, paired with their IDs."
      }
      

      Sie definieren eine einzelne resource vom Typ digitalocean_droplet namens vault. Sie legen ihre Parameter entsprechend den Variablenwerten fest und fügen (mit seinem Fingerabdruck) einen SSH-Schlüssel von Ihrem DigitalOcean-Konto zur Droplet-Ressource hinzu. Sie output die IP-Adressen aller neu erstellten Instanzen an die Konsole aus.

      Speichern und schließen Sie die Datei.

      Initialisieren Sie das Verzeichnis als Terraform-Projekt:

      Sie sehen die folgende Ausgabe:

      Output

      Initializing the backend... Initializing provider plugins... The following providers do not have any version constraints in configuration, so the latest version was installed. To prevent automatic upgrades to new major versions that may contain breaking changes, it is recommended to add version = "..." constraints to the corresponding provider blocks in configuration, with the constraint strings suggested below. * provider.digitalocean: version = "~> 1.14" Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.

      Schritt 4 — Bereitstellung von Vault mit Terraform

      Testen Sie die Gültigkeit Ihrer Konfiguration:

      Sie sehen die folgende Ausgabe:

      Output

      Success! The configuration is valid.

      Führen Sie den Befehl plan aus, um zu sehen, was Terraform bei der Bereitstellung der Infrastruktur versucht:

      • terraform plan -var-file="definitions.tfvars"

      Die Ausgabe wird ähnlich sein wie:

      Output

      Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # digitalocean_droplet.vault[0] will be created + resource "digitalocean_droplet" "vault" { ... } Plan: 1 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.

      Führen Sie den Plan aus:

      • terraform apply -var-file="definitions.tfvars"

      Das Droplet wird die Bereitstellung abschließen und Sie sehen eine Ausgabe, die etwa folgendermaßen aussieht:

      Output

      An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: + digitalocean_droplet.vault-droplet ... Plan: 1 to add, 0 to change, 0 to destroy. ... digitalocean_droplet.vault-droplet: Creating... ... Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Outputs: instance_ip_addr = { "181254240" = "your_new_server_ip" }

      Schritt 5 — Verifizieren Ihres bereitgestellten Droplet

      Führen Sie Folgendes aus, um sich mit Ihrem neuen Droplet zu verbinden:

      Nach der Anmeldung führen Sie Vault aus mit:

      Sie sehen die entsprechende “Hilfe”-Ausgabe:

      Output

      Usage: vault <command> [args] Common commands: read Read data and retrieves secrets write Write data, configuration, and secrets delete Delete secrets and configuration list List data or secrets login Authenticate locally agent Start a Vault agent server Start a Vault server status Print seal and HA status unwrap Unwrap a wrapped secret Other commands: audit Interact with audit devices auth Interact with auth methods debug Runs the debug command kv Interact with Vault's Key-Value storage lease Interact with leases namespace Interact with namespaces operator Perform operator-specific tasks path-help Retrieve API help for paths plugin Interact with Vault plugins and catalog policy Interact with policies print Prints runtime configurations secrets Interact with secrets engines ssh Initiate an SSH session token Interact with tokens

      Zusammenfassung

      Sie verfügen jetzt über ein automatisiertes System zur Bereitstellung von Hashicorp Vault auf DigitalOcean Droplets mit Unterstützung von Terraform und Packer. Um Vault zu verwenden, müssen Sie es initialisieren und weiter konfigurieren. Anweisungen hierzu finden Sie in den Offiziellen Dokumenten.

      Weitere Tutorials zur Verwendung von Terraform finden Sie auf der Terraform Content Page.



      Source link