Kapitel 1. Anwendungen erstellen

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

React ist ein erstaunlich anpassungsfähiges Entwicklungsframework. Entwickler/innen nutzen es, um große JavaScript-lastige Single-Page Applications (SPAs) oder überraschend kleine Plug-ins zu erstellen. Du kannst damit Code in eine Rails-Anwendung einbetten oder eine inhaltsreiche Website erstellen.

In diesem Kapitel schauen wir uns die verschiedenen Möglichkeiten an, eine React-Anwendung zu erstellen. Außerdem gehen wir auf einige der wertvollsten Tools ein, die du in deinen Entwicklungszyklus aufnehmen solltest. Nur noch wenige Menschen erstellen ihre JavaScript-Projekte von Grund auf. Das ist ein mühsamer Prozess, der eine Menge Bastelei und Konfiguration erfordert. Die gute Nachricht ist, dass du den Code, den du brauchst, in fast allen Fällen mit einem Tool erstellen kannst.

Beginnen wir mit der am häufigsten genutzten Methode, um deine React-Reise zu beginnen:create-react-app.

1.1 Erstelle eine einfache Anwendung

Problem

React-Projekte von Grund auf zu erstellen und zu konfigurieren ist eine Herausforderung. Es gibt nicht nur zahlreiche Design-Entscheidungen zu treffen - welche Bibliotheken einbezogen werden sollen, welche Tools verwendet werden sollen, welche Sprachfunktionen aktiviert werden sollen -, sondern manuell erstellte Anwendungen unterscheiden sich auch von Natur aus voneinander. Die Eigenheiten der Projekte verlängern die Zeit, die ein neuer Entwickler braucht, um produktiv zu werden.

Lösung

create-react-app ist ein Tool zum Erstellen von SPAs mit einer Standardstruktur und einer Reihe von Standardoptionen. Die generierten Projekte verwenden die React Scripts-Bibliothek, um den Code zu erstellen, zu testen und auszuführen. Die Projekte haben eine Standard-Webpack-Konfiguration und eine Reihe von Standard-Sprachfunktionen aktiviert.

Jeder Entwickler, der an einer create-react-app Anwendung gearbeitet hat, fühlt sich in jeder anderen sofort zu Hause. Sie verstehen die Projektstruktur und wissen, welche Sprachfunktionen sie nutzen können. Es ist einfach zu bedienen und enthält alle Funktionen, die eine typische Anwendung benötigt: von der Babel-Konfiguration über Dateilader bis hin zu Testbibliotheken und einem Entwicklungsserver.

Wenn du neu in React bist oder eine generische SPA mit einem Minimum an Aufwand erstellen möchtest, solltest du deine App mitcreate-react-app erstellen.

Du kannst den Befehl create-react-app auch global auf deinem Rechner installieren, aber davon wird jetzt abgeraten. Stattdessen solltest du ein neues Projekt erstellen, indem du create-react-app über npx aufrufst. Die Verwendung von npx stellt sicher, dass du deine Anwendung mit der neuesten Version von create-react-app erstellst:

$ npx create-react-app my-app

Dieser Befehl erstellt ein neues Projektverzeichnis namens my-app. Standardmäßig verwendet die Anwendung JavaScript. Wenn du TypeScript als Entwicklungssprache verwenden möchtest, bietet create-react-app eine entsprechende Option:

$ npx create-react-app --template typescript my-app

Facebook hat create-react-app entwickelt. Es sollte also nicht überraschen, dass dein neues Projekt standardmäßig yarn verwendet, wenn du den yarn Paketmanager installiert hast. Um npm zu verwenden, kannst du entweder das Flag --use-npm angeben oder in das Verzeichnis wechseln und die Datei yarn.lock entfernen und dann die Installation mit npm erneut ausführen:

$ cd my-app
$ rm yarn.lock
$ npm install

Um deine Anwendung zu starten, führe das Skript start aus:

$ npm start # or yarn start

Dieser Befehl startet einen Server auf Port 3000 und öffnet einen Browser auf der Startseite, wie in Abbildung 1-1 gezeigt.

Abbildung 1-1. Die generierte Titelseite

Der Server liefert deine Anwendung als ein einziges, großes JavaScript-Bündel aus. Der Code bindet alle seine Komponenten in dieses<div/> in public/index.html ein:

<div id="root"></div>

Der Code zur Erzeugung der Komponenten beginnt in der Datei src/index.js(src/index.tsx, wenn du TypeScript verwendest):

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import reportWebVitals from './reportWebVitals'

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
)

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals()

Diese Datei macht nicht viel mehr, als eine einzelne Komponente namens <App/> zu rendern, die sie aus App.js (oder App.tsx) im selben Verzeichnis importiert:

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

Wenn du diese Datei bearbeitest, während die Anwendung start-ed ist, wird die Seite im Browser automatisch aktualisiert.

Wenn du bereit bist, den Code in Produktion zu geben, musst du eine Reihe von statischen Dateien erzeugen, die du auf einem Standard-Webserver bereitstellen kannst. Dazu führst du das Skript build aus:

$ npm run build

Das Skript build erstellt ein Build-Verzeichnis und veröffentlicht dann eine Reihe von statischen Dateien (siehe Abbildung 1-2).

Abbildung 1-2. Der generierte Inhalt im Build-Verzeichnis

Der Build kopiert viele dieser Dateien aus dem Verzeichnis public/. Der Code für die Anwendung wird in browserfähiges JavaScript umgewandelt und in einer oder mehreren Dateien im Verzeichnis static/js gespeichert. Die von der Anwendung verwendeten Stylesheets werden zusammengefügt und im Verzeichnis static/css gespeichert. Einige der Dateien sind mit Hash-IDs versehen, damit die Browser bei der Bereitstellung deiner Anwendung den neuesten Code herunterladen und nicht eine alte Version aus dem Cache.

Diskussion

create-react-app ist nicht nur ein Werkzeug, um eine neue Anwendung zu erstellen, sondern auch eine Plattform, um deine React-Anwendung mit den neuesten Tools und Bibliotheken auf dem neuesten Stand zu halten. Du kannst die Bibliothek react-scripts wie jede andere aktualisieren: indem du die Versionsnummer änderst und npm install erneut ausführst. Du brauchst keine Liste von Babel-Plugins oder Postcss-Bibliotheken zu verwalten oder eine komplexewebpack.config.js-Datei zu pflegen. Die Bibliothek react-scripts verwaltet sie alle für dich.

Die Konfiguration ist natürlich immer noch da, aber tief im Verzeichnis react-scripts vergraben. Dort findest du die Datei webpack.config.js, die alle Babel-Konfigurationen und Dateilader enthält, die deine Anwendung verwenden wird. Da es sich um eine Bibliothek handelt, kannst du React Scripts genau wie jede andere Abhängigkeit aktualisieren.

Wenn du dich jedoch später dafür entscheidest, all das selbst zu verwalten, kannst du das tun. Wenn du die Anwendung auswirfst, kommt alles wieder unter deine Kontrolle:

$ npm run eject

Dies ist jedoch eine einmalige Änderung. Wenn du deine Bewerbung einmal rausgeworfen hast, gibt es kein Zurück mehr. Bevor du eine Anwendung auswirfst, solltest du dir das gut überlegen. Es kann sein, dass die Konfiguration, die du brauchst, bereits vorhanden ist. Zum Beispiel werfen Entwickler oft eine Anwendung aus, um auf TypeScript umzusteigen. Mit der Option --template typescript ist das jetzt nicht mehr nötig.

Ein weiterer häufiger Grund für das Auswerfen war das Proxying von Webdiensten. React-Apps müssen sich oft mit einem separaten API-Backend verbinden. Früher haben die Entwickler dies getan, indem sie Webpack so konfiguriert haben, dass es einen entfernten Server über den lokalen Entwicklungsserver projiziert. Jetzt kannst du das vermeiden, indem du einen Proxy in der package.json-Datei einstellst:

"proxy": "http://myapiserver",

Wenn dein Code nun eine URL kontaktiert, die der Server lokal nicht finden kann(/api/thing), leitet die react-scripts diese Anfragen automatisch an http://myapiserver/api/thing weiter .

Tipp

Wenn du kannst, vermeide das Auswerfen deiner Anwendung. Schau in der Dokumentation voncreate-react-app nach, ob du die Änderung auf andere Weise vornehmen kannst.

Du kannst den Quellcode für dieses Rezept in JavaScript oder TypeScript von derGitHub-Seite herunterladen.

1.2 Erstellen von inhaltsreichen Apps mit Gatsby

Problem

Inhaltsreiche Websites wie Blogs und Online-Shops müssen große Mengen an komplexen Inhalten effizient bereitstellen. Ein Tool wiecreate-react-app ist für diese Art von Website nicht geeignet, weil es alles als ein einziges großes JavaScript-Bündel ausliefert, das ein Browser herunterladen muss, bevor etwas angezeigt wird.

Lösung

Wenn du eine inhaltsreiche Website aufbaust, solltest du Gatsby verwenden.

Gatsby konzentriert sich darauf, Inhalte so effizient wie möglich zu laden, umzuwandeln und auszuliefern. Es kann statische Versionen von Webseiten generieren, was bedeutet, dass die Antwortzeiten von Gatsby-Websites oft deutlich langsamer sind als z. B. solche, die mitcreate-react-app erstellt wurden.

Gatsby verfügt über viele Plugins, die Daten effizient aus statischen lokalen Daten, GraphQL-Quellen und Content Management Systemen von Drittanbietern wieWordPress laden und umwandeln können.

Du kannst gatsby global installieren, aber du kannst es auch über den Befehl npx ausführen:

$ npx gatsby new my-app

Der Befehl gatsby new erstellt ein neues Projekt in einem Unterverzeichnis namens my-app. Wenn du diesen Befehl zum ersten Mal ausführst, fragt er dich, welchen Paketmanager du verwenden möchtest: entweder yarn oder npm.

Um deine Anwendung zu starten, wechselst du in das neue Verzeichnis und führst sie im Entwicklungsmodus aus:

$ cd my-app
$ npm run develop

Du kannst deine Anwendung dann unter http://localhost:8000 öffnen , wie in Abbildung 1-3 gezeigt.

Abbildung 1-3. Gatsby-Seite auf http://localhost:8000

Gatsby-Projekte haben eine einfache Struktur, wie in Abbildung 1-4 dargestellt.

Abbildung 1-4. Die Gatsby-Verzeichnisstruktur

Der Kern der Anwendung befindet sich im Verzeichnis src. Jede Seite innerhalb einer Gatsby-Anwendung hat ihre eigene React-Komponente. Dies ist die Startseite der Standardanwendung in index.js:

import * as React from "react"
import { Link } from "gatsby"
import { StaticImage } from "gatsby-plugin-image"

import Layout from "../components/layout"
import Seo from "../components/seo"

const IndexPage = () => (
  <Layout>
    <Seo title="Home" />
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <StaticImage
      src="../images/gatsby-astronaut.png"
      width={300}
      quality={95}
      formats={["AUTO", "WEBP", "AVIF"]}
      alt="A Gatsby astronaut"
      style={{ marginBottom: `1.45rem` }}
    />
    <p>
      <Link to="/page-2/">Go to page 2</Link> <br />
      <Link to="/using-typescript/">Go to "Using TypeScript"</Link>
    </p>
  </Layout>
)

export default IndexPage

Es ist nicht nötig, eine Route für die Seite zu erstellen. Jeder Seitenkomponente wird automatisch eine Route zugewiesen. Zum Beispiel ist die Seite untersrc/pages/using-typescript.tsxautomatischunter using-typescript verfügbar.1 Dieser Ansatz hat mehrere Vorteile. Erstens musst du, wenn du viele Seiten hast, die Routen für diese Seiten nicht manuell verwalten. Zweitens bedeutet es, dass Gatsby viel schneller liefern kann. Um zu sehen, warum das so ist, schauen wir uns an, wie man einen Produktions-Build für eine Gatsby-Anwendung erstellt.

Wenn du den Gatsby-Entwicklungsserver stoppst,2 kannst du einen Produktions-Build wie folgt erstellen:

$ npm run build

Dieser Befehl führt einen gatsby build Befehl aus, der ein öffentliches Verzeichnis erstellt. Und genau in diesem öffentlichen Verzeichnis liegt die wahre Magie von Gatsby. Für jede Seite findest du zwei Dateien. Erstens, eine generierte JavaScript-Datei:

1389 06:48 component---src-pages-using-typescript-tsx-93b78cfadc08d7d203c6.js

Hier kannst du sehen, dass der Code für using-typescript.tsx nur 1.389 Bytes lang ist, was mit dem Core Framework gerade genug JavaScript ist, um die Seite zu erstellen. Es ist nicht die Art von Include-Alles-Skript, die du in einem create-react-app Projekt findest.

Zweitens gibt es für jede Seite ein Unterverzeichnis mit einer generierten HTML-Datei. Für using-typescript.tsx heißt die Dateipublic/using-typescript/index.html und enthält eine statisch generierte Version der Webseite. Sie enthält den HTML-Code, den die Komponenteusing-typescript.tsx sonst dynamisch rendern würde. Am Ende der Webseite lädt sie die JavaScript-Version der Seite, um alle dynamischen Inhalte zu erzeugen.

Diese Dateistruktur bedeutet, dass Gatsby-Seiten genauso schnell geladen werden wie statische Seiten. Mit, der gebündelten react-helmet Bibliothek, kannst du auch <meta/> Header-Tags mit zusätzlichen Informationen über deine Website erstellen. Beide Funktionen sind ideal für die Suchmaschinenoptimierung (SEO).

Diskussion

Wie kommen die Inhalte in deine Gatsby-Anwendung? Du kannst ein Headless Content Management System, einen GraphQL-Dienst, eine statische Datenquelle oder etwas anderes verwenden. Zum Glück gibt es in Gatsby viele Plugins, mit denen du Datenquellen mit deiner Anwendung verbinden und die Inhalte aus anderen Formaten, wie z. B. Markdown, in HTML umwandeln kannst.

Ein komplettes Set an Plugins findest du auf der Gatsby-Website.

Meistens wählst du die Plugins, die du brauchst, wenn du das Projekt zum ersten Mal erstellst. Um dir einen Vorsprung zu verschaffen, unterstützt Gatsby auchStartvorlagen. Die Vorlage stellt die anfängliche Anwendungsstruktur und -konfiguration bereit. Die App, die wir vorhin gebaut haben, verwendet das Standard-Startertemplate, das recht einfach ist. Die Datei gatsby-config.js im Stammverzeichnis der Anwendung legt fest, welche Plugins deine Anwendung verwendet.

Aber es gibt massenhaft Gatsby-Starter, die vorkonfiguriert sind, um Anwendungen zu erstellen, die sich mit verschiedenen Datenquellen verbinden, mit vorkonfigurierten Optionen für SEO, Styling, Offline-Caching, progressive Webanwendungen (PWAs) und mehr. Egal, welche Art von inhaltsreicher Anwendung du erstellst, es gibt einen Starter, der genau deinen Bedürfnissen entspricht.

Auf der Gatsby-Website findest du weitere Informationen über Gatsby-Starter sowie einenSpickzettel mit den nützlichsten Tools und Befehlen.

Du kannst den Quellcode für dieses Rezept von der GitHub-Seite herunterladen.

1.3 Universal Apps mit Razzle erstellen

Problem

Wenn du mit der Entwicklung einer Anwendung beginnst, ist nicht immer klar, welche Entscheidungen für die Architektur wichtig sind. Solltest du eine SPA erstellen? Solltest du Server Side R verwenden, wenn die Leistung entscheidend ist? Du musst dich entscheiden, welche Plattform du einsetzen willst und ob du deinen Code in JavaScript oder TypeScript schreiben willst.

Viele Tools verlangen, dass du diese Fragen frühzeitig beantwortest. Wenn du später deine Meinung änderst, kann es kompliziert sein, die Art und Weise, wie du deine Anwendung erstellst und einsetzt, zu ändern.

Lösung

Wenn du Entscheidungen darüber, wie du deine Anwendung erstellst und einsetzt, aufschieben willst, solltest duRazzle in Betracht ziehen.

Razzle ist ein Tool zum Erstellen von Universal-Anwendungen: Anwendungen, die ihr JavaScript auf dem Server ausführen können. Oder auf dem Client. Oder beides.

Razzle verwendet eine Plugin-Architektur, die es dir ermöglicht, deine Meinung darüber zu ändern, wie du deine Anwendung erstellst. Du kannst sogar entscheiden, ob du deinen Code in React, Preact oder einem anderen Framework wie Elm oder Vue erstellen willst.

Du kannst eine Razzle-Anwendung mit dem Befehl create-razzle-app erstellen:3

$ npx create-razzle-app my-app

Dieser Befehl erstellt ein neues Razzle-Projekt im Unterverzeichnis my-app. Du kannst den Entwicklungsserver mit dem Skript startstarten:

$ cd my-app
$ npm run start

Das Skript start erstellt dynamisch sowohl den Client- als auch den Servercode und führt dann den Server auf Port 3000 aus, wie in Abbildung 1-5 gezeigt.

Abbildung 1-5. Die Razzle-Startseite unter http://localhost:3000

Wenn du eine Produktionsversion deiner Anwendung einsetzen willst, kannst du das Skript build ausführen:

$ npm run build

Im Gegensatz zu create-react-app wird hier nicht nur der Client-Code, sondern auch ein Node-Server erstellt. Razzle erzeugt den Code im Unterverzeichnisbuild. Der Servercode wird zur Laufzeit weiterhin statischen Code für deinen Client erzeugen. Du kannst einen Produktionsserver starten, indem du die Datei build/server.js mit dem Skript start:prod ausführst:

$ npm run start:prod

Du kannst den Produktionsserver überall dort einsetzen, wo Node verfügbar ist.

Der Server und der Client können beide denselben Code ausführen, was ihn universell macht. Aber wie macht sie das?

Der Client und der Server haben unterschiedliche Einstiegspunkte. Der Server führt den Code in src/server.js aus; der Browser führt den Code insrc/client.js aus. Sowohl server.js als auch client.js rendern dann dieselbe App mit src/App.js.

Wenn du deine Anwendung als SPA betreiben willst, entferne die Dateien src/index.js und src/server.js. Erstelle dann eine index.html-Datei imöffentlichen Ordner, die eine <div/> mit der ID root enthält, und baue die Anwendung mit dieser neu auf:

$ node_modules/.bin/razzle build --type=spa
Tipp

Um deine Anwendung jedes Mal als SPA zu bauen, füge --type=spa zu den Skripten start und build in package.json hinzu.

Du wirst eine vollständige SPA in build/public/ erzeugen, die du auf jedem Webserver einsetzen kannst.

Diskussion

Razzle ist so anpassungsfähig, weil es aus einer Reihe von hochgradig konfigurierbaren Plugins aufgebaut ist. Jedes Plugin ist eine Funktion höherer Ordnung, die eine Webpack-Konfiguration empfängt und eine geänderte Version zurückgibt. Ein Plugin kann TypeScript-Code transpilieren, ein anderes kann die React-Bibliotheken bündeln.

Wenn du deine Anwendung auf Vue umstellen willst, musst du nur die Plugins ersetzen, die du verwendest.

Eine Liste der verfügbaren Plugins findest du auf der Razzle-Website.

Du kannst den Quellcode für dieses Rezept von der GitHub-Seite herunterladen.

1.4 Verwalten von Server- und Client-Code mit Next.js

Problem

React erzeugt Client-Code - auch wenn der Client-Code auf dem Server erzeugt wird. Manchmal hast du aber vielleicht eine relativ kleine Menge an API-Code (Application Programming Interface), den du lieber als Teil derselben React-Anwendung verwalten möchtest.

Lösung

Next.js ist ein Tool zum Erstellen von React-Anwendungen und Servercode. Die API-Endpunkte und die Client-Seiten verwenden Standard-Routing-Konventionen, so dass sie einfacher zu erstellen und einzusetzen sind, als wenn du sie selbst verwalten würdest. Alle Details zu Next.js findest du auf der Website.

Mit diesem Befehl kannst du eine Next.js-Anwendung erstellen:

$ npx create-next-app my-app

Dabei wird yarn als Paketmanager verwendet, wenn du ihn installiert hast. Mit dem Flag--user-npm kannst du die Verwendung des Paketmanagers npm erzwingen:

$ npx create-next-app --use-npm my-app

Dadurch wird eine Next.js-Anwendung im Unterverzeichnis my-app erstellt. Um die Anwendung zu starten, führe das Skript dev aus (siehe Abbildung 1-6):

$ cd my-app
$ npm run dev
Abbildung 1-6. Eine Next.js-Seite, die unter http://localhost:3000 läuft.

Next.js ermöglicht es dir, Seiten zu erstellen, ohne dass du eine Routing-Konfiguration vornehmen musst. Wenn du ein Komponentenskript in den Ordnerpages einfügst, wird es sofort über den Server verfügbar. Die Komponente pages/index.js erzeugt zum Beispiel die Startseite der Standardanwendung.

Dieser Ansatz ist ähnlich wie der von Gatsby,4 wird aber in Next.js weitergeführt, um serverseitigen Code einzubeziehen.

Next.js-Anwendungen enthalten in der Regel etwas API-Servercode, was für React-Anwendungen ungewöhnlich ist, die oft getrennt vom Servercode erstellt werden. Aber wenn du in pages/api nachschaust, findest du einen Beispiel-Server-Endpunkt namens hello.js:

// Next.js API route support: https://nextjs.org/docs/api-routes/introduction

export default (req, res) => {
  res.status(200).json({ name: 'John Doe' })
}

Das Routing zum Endpunkt api/hello geschieht automatisch.

Next.js überträgt deinen Code in ein verstecktes Verzeichnis namens .next, das es dann an einen Dienst wie die Next.js-eigeneVercel-Plattform weiterleiten kann.

Wenn du willst, generierst du einen statischen Build deiner Anwendung mit:

$ node_modules/.bin/next export

Der Befehl export erstellt deinen Client-Code in einem Verzeichnis namens out. Der Befehl wandelt jede Seite in eine statisch gerenderte HTML-Datei um, die schnell im Browser geladen wird. Am Ende der Seite wird die JavaScript-Version geladen, um alle dynamischen Inhalte zu erzeugen.

Warnung

Wenn du eine exportierte Version einer Next.js-Anwendung erstellst, enthält sie keine serverseitigen APIs.

Next.js kommt mit einer Reihe von Datenabrufoptionen, mit denen du Daten aus statischen Inhalten oder überHeadless Content Management System (CMS)-Quellen beziehen kannst.

Diskussion

Next.js ist in vielerlei Hinsicht ähnlich wie Gatsby. Der Schwerpunkt liegt auf der Geschwindigkeit der Bereitstellung und einem geringen Konfigurationsaufwand. Es ist wahrscheinlich am vorteilhaftesten für Teams, die nur sehr wenig Servercode haben werden.

Du kannst den Quellcode für dieses Rezept von derGitHub-Seite herunterladen.

1.5 Eine winzige App mit Preact erstellen

Problem

React-Anwendungen können sehr groß sein. Es ist ziemlich einfach, eine einfache React-Anwendung zu erstellen, die in JavaScript-Codebündel mit einer Größe von mehreren hundert Kilobytes umgesetzt wird. Vielleicht möchtest du eine Anwendung mit React-ähnlichen Funktionen erstellen, die aber viel weniger Platz benötigt.

Lösung

Wenn du React-Funktionen möchtest, aber nicht den Preis für ein JavaScript-Bundle in React-Größe zahlen willst, solltest du Preact in Betracht ziehen.

Preact ist nicht React. Es ist eine eigenständige Bibliothek, die so nah wie möglich an React herankommen soll, aber viel kleiner ist.

Der Grund, warum das React-Framework so groß ist, liegt in der Art und Weise, wie es funktioniert. React-Komponenten erzeugen nicht direkt Elemente im Document Object Model (DOM) des Browsers. Stattdessen bauen sie Elemente in einem virtuellen DOM auf und aktualisieren dann das tatsächliche DOM in regelmäßigen Abständen. Auf diese Weise kann das grundlegende DOM-Rendering schnell sein, da das tatsächliche DOM nur dann aktualisiert werden muss, wenn es tatsächlich Änderungen gibt. Das hat allerdings auch einen Nachteil. Das virtuelle DOM von React benötigt eine Menge Code, um es auf dem neuesten Stand zu halten. Es muss ein ganzes synthetisches Ereignismodell verwalten, das dem des Browsers entspricht. Aus diesem Grund ist das React-Framework sehr umfangreich und der Download kann einige Zeit in Anspruch nehmen.

Eine Möglichkeit, dies zu umgehen, ist der Einsatz von Techniken wie SSR, aber SSR kann kompliziert zu konfigurieren sein.5 Manchmal möchtest du nur eine kleine Menge an Code herunterladen. Und genau dafür gibt es Preact.

Die Preact-Bibliothek ist zwar ähnlich wie React, aber sehr klein. Zum Zeitpunkt der Erstellung dieses Artikels ist die Preact-Hauptbibliothek etwa 4 KB groß. Das ist so klein, dass es möglich ist, React-ähnliche Funktionen zu Webseiten hinzuzufügen, und zwar mit kaum mehr Code, als zum Schreiben von nativemJavaScript erforderlich ist.

Preact lässt dir die Wahl, wie du es verwenden willst: als kleine JavaScript-Bibliothek, die in eine Webseite eingebunden wird (der No-Tools-Ansatz ) oder als vollwertige JavaScript-Anwendung.

Der No-Tools-Ansatz ist grundlegend. Die Preact-Kernbibliothek unterstützt JSX nicht, und du hast keine Unterstützung für Babel, sodass du kein modernes JavaScript verwenden kannst. Hier ist eine Beispiel-Webseite, die die Preact-Bibliothek verwendet:

<html>
    <head>
        <title>No Tools!</title>
        <script src="https://unpkg.com/preact?umd"></script>
    </head>
    <body>
        <h1>No Tools Preact App!</h1>
        <div id="root"></div>
        <script>
         var h = window.preact.h;
         var render = window.preact.render;

         var mount = document.getElementById('root');

         render(
             h('button',
               {
                   onClick: function() {
                       render(h('div', null, 'Hello'), mount);
                   }
               },
               'Click!'),
             mount
         );
        </script>
    </body>
</html>

Diese Anwendung wird sich auf <div/> mit der ID root einbinden, wo sie eine Schaltfläche anzeigt. Wenn du auf die Schaltfläche klickst, ersetzt sie den Inhalt des Stammverzeichnisses div durch die Zeichenkette "Hello". Einfacher kann eine Preact-Anwendung nicht sein.

Du würdest selten eine Anwendung auf diese Weise schreiben. In Wirklichkeit würdest du eine einfache Build-Chain erstellen, die zumindest modernes JavaScript unterstützt.

Preact unterstützt das gesamte Spektrum von JavaScript-Anwendungen. Das andere Extrem ist, dass du eine komplette Preact-Anwendung mit preact-cli erstellen kannst.

preact-cli ist ein Tool zum Erstellen von Preact-Projekten und ist analog zu Tools wie create-react-app. Du kannst eine Preact-Anwendung mit erstellen:

$ npx preact-cli create default my-app
Tipp

Dieser Befehl verwendet die Standardvorlage. Für die Erstellung von Projekten, die z. B. Materialkomponenten oder TypeScript verwenden, sind weitere Templates verfügbar. Weitere Informationen findest du auf der Preact GitHub-Seite.

Mit diesem Befehl wird deine neue Preact-Anwendung im Unterverzeichnis my-app erstellt. Um sie zu starten, führe das Skript dev aus:

$ cd my-app
$ npm run dev

Der Server läuft auf Port 8080, wie in Abbildung 1-7 dargestellt.

Abbildung 1-7. Eine Seite aus Preact

Der Server generiert eine Webseite, die ein JavaScript-Bündel abruft, das aus dem Code in src/index.js erstellt wurde.

Du hast jetzt eine vollwertige React-ähnliche Anwendung. Der Code in der Komponente Home (src/routes/home/index.js) sieht zum Beispiel sehr React-ähnlich aus, mit voller JSX-Unterstützung:

import { h } from 'preact';
import style from './style.css';

const Home = () => (
    <div class={style.home}>
        <h1>Home</h1>
        <p>This is the Home component.</p>
    </div>
);

export default Home;

Der einzige wesentliche Unterschied zu einer normalen React-Komponente besteht darin, dass eine Funktion namens h aus der Bibliothek preactimportiert wird, anstatt React aus der Bibliothek react zu importieren.

Hinweis

Das JSX im Preact-Code wird in eine Reihe von Aufrufen der Funktion h umgewandelt und muss deshalb importiert werden. Aus demselben Grund mussten auch Anwendungen, die vor Version 17 mit create-react-app erstellt wurden, dasreact Objekt importieren. Seit Version 17 verwendet create-react-app nun dieJSX-Transformation, sodass reactnicht mehr jedes Mal importiert werden muss. Es ist jederzeit möglich, dass zukünftige Versionen von Preact eine ähnliche Änderung vornehmen werden.

Allerdings ist die Größe der Anwendung gestiegen: Sie ist jetzt etwas über 300 KB groß. Das ist ziemlich groß, aber wir befinden uns noch im Entwicklungsmodus. Um die wahre Leistung von Preact zu sehen, halte den Dev-Server mit Strg-C an und führe dann das Skript build aus:

$ npm run build

Mit diesem Befehl wird eine statische Version der Anwendung im Build-Verzeichnis erstellt. Das hat erstens den Vorteil, dass eine statische Kopie der Startseite erstellt wird, die schnell gerendert werden kann. Zweitens wird der gesamte ungenutzte Code aus der Anwendung entfernt und alles verkleinert. Wenn du diese erstellte Version der Anwendung auf einem Standard-Webserver bereitstellst, überträgt der Browser nur etwa 50-60 KB, wenn er geöffnet wird.

Diskussion

Preact ist ein bemerkenswertes Projekt. Obwohl es ganz anders funktioniert als React, bietet es praktisch die gleiche Leistung bei einem Bruchteil der Größe. Und die Tatsache, dass du es für alles verwenden kannst, vom einfachen Inline-Code bis hin zu einem ausgewachsenen SPA, bedeutet, dass es eine Überlegung wert ist, wenn die Codegröße für dein Projekt entscheidend ist.

Mehr über Preact erfährst du auf der Preact-Website.

Du kannst den Quellcode für das No-Tools-Beispiel und das größere Preact-Beispiel von der GitHub-Seite herunterladen.

Wenn du Preact noch mehr wie React aussehen lassen möchtest, schau dir die preact-compat-Bibliothekan.

Wenn du ein Projekt suchst, das einen ähnlichen Ansatz wie Preact verfolgt, dann schau dir InfernoJS an.

1.6 Bibliotheken mit nwb bauen

Problem

Große Unternehmen entwickeln oft mehrere React-Anwendungen gleichzeitig. Wenn du ein Beratungsunternehmen bist, erstellst du vielleicht Anwendungen für mehrere Organisationen. Wenn du ein Softwarehaus bist, erstellst du vielleicht verschiedene Anwendungen, die das gleiche Erscheinungsbild haben sollen, sodass du wahrscheinlich gemeinsame Komponenten erstellen willst, die in mehreren Anwendungen verwendet werden können.

Wenn du ein Komponentenprojekt erstellst, musst du eine Verzeichnisstruktur anlegen, eine Reihe von Werkzeugen und Sprachfunktionen auswählen und eine Build-Chain erstellen, die deine Komponente in einem einsatzfähigen Format bündelt. Dieser Prozess kann genauso mühsam sein wie die manuelle Erstellung eines Projekts für eine ganze React-Anwendung.

Lösung

Mit dem nwb Toolkit kannst du komplette React-Anwendungen oder einzelne React-Komponenten erstellen. Es kann auch Komponenten für die Verwendung in Preact- und InfernoJS-Projekten erstellen, aber wir konzentrieren uns hier auf React-Komponenten.

Um ein neues React-Komponentenprojekt zu erstellen, musst du zunächst das Tool nwb global installieren:

$ npm install -g nwb

Du kannst dann mit dem Befehl nwb ein neues Projekt erstellen:

$ nwb new react-component my-component
Hinweis

Wenn du nicht nur eine einzelne Komponente, sondern eine ganze nwb Anwendung erstellen möchtest, kannst du react-component in diesem Befehl durch react-app, preact-app oder inferno-app ersetzen, um eine Anwendung im angegebenen Framework zu erstellen. Du kannst auchvanilla-app verwenden, wenn du ein einfaches JavaScript-Projekt ohne einFramework erstellen möchtest.

Wenn du diesen Befehl ausführst, werden dir mehrere Fragen zu der Art der Bibliothek gestellt, die du bauen willst. Er wird dich zum Beispiel fragen, ob du ECMAScript-Module bauen willst:

Creating a react-component project...
? Do you want to create an ES modules build? (Y/n)

Mit dieser Option kannst du eine Version erstellen, die eine export Anweisung enthält, anhand derer Webpack entscheiden kann, ob es die Komponente in eine Client-Anwendung aufnehmen muss. Du wirst auch gefragt, ob du eine Universal Module Definition (UMD) erstellen möchtest:

? Do you want to create a UMD build? (y/N)

Das ist nützlich, wenn du deine Komponente in eine <script/> innerhalb einer Webseite einbinden willst. Für unser Beispiel werden wir keinen UMD-Build erstellen.

Nach den Fragen wird das Tool ein nwb Komponentenprojekt im Unterverzeichnis my-component erstellen. Das Projekt wird mit einer einfachen Wrapper-Anwendung geliefert, die du mit dem Skript start starten kannst:

$ cd my-component
$ npm run start

Die Demoanwendung läuft auf Port 3000, wie in Abbildung 1-8 gezeigt.

Abbildung 1-8. Eine nwb Komponente

Die Anwendung wird eine einzelne Komponente enthalten, die in src/index.js definiert ist:

import React, { Component } from 'react'

export default class extends Component {
  render() {
    return (
      <div>
        <h2>Welcome to React components</h2>
      </div>
    )
  }
}

Du kannst die Komponente nun wie jedes andere React-Projekt erstellen. Wenn du bereit bist, eine veröffentlichbare Version zu erstellen, gibst du ein:

$ npm run build

Die erstellte Komponente befindet sich in der Datei lib/index.js, die du in einem Repository zur Verwendung in anderen Projekten bereitstellen kannst.

Diskussion

Weitere Informationen zur Erstellung von nwb Komponenten findest du im nwb Leitfaden zur Entwicklung von Komponenten und Bibliotheken.

Du kannst den Quellcode für dieses Rezept von der GitHub-Seite herunterladen.

1.7 React zu Rails hinzufügen mit Webpacker

Problem

Das Rails-Framework wurde entwickelt, bevor interaktive JavaScript-Anwendungen populär wurden. Rails-Anwendungen folgen einem eher traditionellen Modell für die Entwicklung von Webanwendungen, bei dem HTML-Seiten auf dem Server als Antwort auf Browseranfragen generiert werden. Aber manchmal möchtest du vielleicht mehr interaktive Elemente in eine Rails-Anwendung einbauen.

Lösung

Du kannst die Webpacker-Bibliothek verwenden, um React-Anwendungen in mit Rails erstellte Webseiten einzufügen. Um zu sehen, wie es funktioniert, erstellen wir zunächst eine Rails-Anwendung, die Webpacker enthält:

$ rails new my-app --webpack=react

Mit diesem Befehl wird eine Rails-Anwendung in einem Verzeichnis namens my-app erstellt, die so vorkonfiguriert ist, dass sie auf einem Webpacker-Server läuft. Bevor wir die Anwendung starten, wollen wir eine Beispielseite/einen Beispielcontroller erstellen:

$ cd my-app
$ rails generate controller Example index

Dieser Code erzeugt diese Templating-Seite unter app/views/example/index.html.erb:

<h1>Example#index</h1>
<p>Find me in app/views/example/index.html.erb</p>

Als Nächstes müssen wir eine kleine React-Anwendung erstellen, die wir in diese Seite einfügen können. Rails fügt Webpacker-Anwendungen alsPacks ein: kleine JavaScript-Bündel innerhalb von Rails. Wir erstellen ein neues Pack in app/javascript/packs/counter.js, das eine einfache Zählerkomponente enthält:

import React, { useState } from 'react'
import ReactDOM from 'react-dom'

const Counter = (props) => {
  const [count, setCount] = useState(0)
  return (
    <div className="Counter">
      You have clicked the button {count} times.
      <button onClick={() => setCount((c) => c + 1)}>Click!</button>
    </div>
  )
}

document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <Counter />,
    document.body.appendChild(document.createElement('div'))
  )
})

Diese Anwendung aktualisiert einen Zähler jedes Mal, wenn ein Nutzer auf die Schaltfläche klickt.

Wir können das Paket nun in die Webseite einfügen, indem wir eine einzige Codezeile in die Vorlagenseite einfügen:

<h1>Example#index</h1>
<p>Find me in app/views/example/index.html.erb</p>
<%= javascript_pack_tag 'counter' %>

Schließlich können wir den Rails-Server auf Port 3000 laufen lassen:

$ rails server
Warnung

Zum Zeitpunkt der Erstellung dieses Artikels musst du den yarn Paketmanager installiert haben, wenn du den Server startest. Du kannst yarnglobal mit npm install -g yarn installieren.

Du siehst die Seite http://localhost:3000/example/index.html in Abbildung 1-9.

Abbildung 1-9. Eine in http://localhost:3000/example/index.html eingebettete React-App

Diskussion

Wie du wahrscheinlich schon vermutet hast, wandelt Webpacker die Anwendung hinter den Kulissen mit einer Kopie von Webpack um, die du mit der Konfigurationsdatei app/config/webpacker.yml konfigurieren kannst.

Webpacker wird neben dem Rails-Code verwendet und nicht als Ersatz für diesen. Du solltest den Einsatz in Betracht ziehen, wenn deine Rails-Anwendung ein wenig zusätzliche Interaktivität benötigt.

Du kannst mehr über Webpacker auf der Webpacker GitHub Seite erfahren.

Du kannst den Quellcode für dieses Rezept von der GitHub-Seite herunterladen.

1.8 Benutzerdefinierte Elemente mit Preact erstellen

Problem

Unter bestimmten Umständen ist es schwierig, React-Code in bestehende Inhalte einzufügen. In einigen CMS-Konfigurationen ist es den Nutzern zum Beispiel nicht erlaubt, zusätzliches JavaScript in den Text einer Seite einzufügen. In diesen Fällen wäre es hilfreich, eine standardisierte Möglichkeit zu haben, JavaScript-Anwendungen sicher in eine Seite einzufügen.

Lösung

Benutzerdefinierte Elemente sind eine Standardmethode zur Erstellung neuer HTML-Elemente, die du auf einer Webseite verwenden kannst. Sie erweitern die HTML-Sprache, indem sie dem Benutzer mehr Tags zur Verfügung stellen.

In diesem Rezept geht es darum, wie wir ein leichtgewichtiges Framework wie Preact verwenden können, um benutzerdefinierte Elemente zu erstellen, die wir auf einem Drittanbieter-Server veröffentlichen können.

Beginnen wir damit, eine neue Preact-Anwendung zu erstellen. Diese Anwendung wird das benutzerdefinierte Element bereitstellen, das wir an anderer Stelle verwenden können:6

$ preact create default my-element

Jetzt wechseln wir in das Verzeichnis der App und fügen die Bibliothek preact-custom-element zum Projekt hinzu:

$ cd my-element
$ npm install preact-custom-element

Die Bibliothek preact-custom-element ermöglicht es uns, ein neues benutzerdefiniertes HTML-Element in einem Browser zu registrieren.

Als Nächstes müssen wir die Datei src/index.js des Preact-Projekts so ändern, dass sie ein neues benutzerdefiniertes Element registriert, das wircomponents/Converter/index.js nennen werden:

import register from 'preact-custom-element'
import Converter from './components/Converter'

register(Converter, 'x-converter', ['currency'])

Die Methode register teilt dem Browser mit, dass wir ein neues benutzerdefiniertes HTML-Element namens <x-converter/> erstellen wollen, das eine einzige Eigenschaft namens currency hat, die wir in src/components/Converter/index.js definieren werden:

import { h } from 'preact'
import { useEffect, useState } from 'preact/hooks'
import 'style/index.css'

const rates = { gbp: 0.81, eur: 0.92, jpy: 106.64 }

export default ({ currency = 'gbp' }) => {
  const [curr, setCurr] = useState(currency)
  const [amount, setAmount] = useState(0)

  useEffect(() => {
    setCurr(currency)
  }, [currency])

  return (
    <div className="Converter">
      <p>
        <label htmlFor="currency">Currency: </label>
        <select
          name="currency"
          value={curr}
          onChange={(evt) => setCurr(evt.target.value)}
        >
          {Object.keys(rates).map((r) => (
            <option value={r}>{r}</option>
          ))}
        </select>
      </p>
      <p className="Converter-amount">
        <label htmlFor="amount">Amount: </label>
        <input
          name="amount"
          size={8}
          type="number"
          value={amount}
          onInput={(evt) => setAmount(parseFloat(evt.target.value))}
        />
      </p>
      <p>
        Cost:
        {((amount || 0) / rates[curr]).toLocaleString('en-US', {
          style: 'currency',
          currency: 'USD',
        })}
      </p>
    </div>
  )
}
Hinweis

Um mit der Spezifikation für benutzerdefinierte Elemente konform zu sein, müssen wir einen Namen für unser Element wählen, der mit einem Kleinbuchstaben beginnt, keine Großbuchstaben enthält und einen Bindestrich beinhaltet.7 Diese Konvention stellt sicher, dass der Name nicht mit einem Standard-Elementnamen kollidiert.

Unsere Converter Komponente ist ein Währungsumrechner, der in unserem Beispiel einen festen Satz von Wechselkursen verwendet. Wenn wir nun unseren Preact-Server starten:

$ npm run dev

wird das JavaScript für das benutzerdefinierte Element unter http://localhost:8080/bundle.js verfügbar sein .

Um dieses neue benutzerdefinierte Element zu verwenden, erstellen wir irgendwo eine statische Webseite mit diesem HTML-Code:

<html>
    <head>
        <script src="https://unpkg.com/babel-polyfill/dist/polyfill.min.js">
        </script>
        <script src="https://unpkg.com/@webcomponents/webcomponentsjs">
        </script>
        <!-- Replace this with the address of your custom element -->
        <script type="text/javascript" src="http://localhost:8080/bundle.js">
        </script>
    </head>
    <body>
        <h1>Custom Web Element</h1>
        <div style="float: right; clear: both">
            <!-- This tag will insert the Preact app -->
            <x-converter currency="jpy"/>
        </div>
        <p>This page contains an example custom element called
            <code>&lt;x-converter/&gt;</code>,
            which is being served from a different location</p>
    </body>
</html>

Diese Webseite enthält die Definition des benutzerdefinierten Elements in der endgültigen <script/> des <head/> Elements. Um sicherzustellen, dass das benutzerdefinierte Element sowohl in neuen als auch in alten Browsern verfügbar ist, fügen wir außerdem ein paar Shims von unpkg.com hinzu.

Jetzt, wo wir den Code des benutzerdefinierten Elements in die Webseite eingefügt haben, können wir<x-converter/> Tags in den Code einfügen, so als wären sie Teil des Standard-HTML. In unserem Beispiel übergeben wir außerdem eine currency Eigenschaft an die zugrunde liegendePreact-Komponente.

Warnung

Benutzerdefinierte Elementeigenschaften werden mit Namen in Kleinbuchstaben an die zugrunde liegende Komponente übergeben, unabhängig davon, wie wir sie in der HTML-Datei definieren.

Wir können diese Seite über einen Webserver ausführen, der vom Preact-Server getrennt ist. Abbildung 1-10 zeigt das neue benutzerdefinierte Element.

Abbildung 1-10. Das benutzerdefinierte Element eingebettet in eine statische Seite

Diskussion

Das benutzerdefinierte Element muss sich nicht auf demselben Server befinden wie die Webseite, die es verwendet, was bedeutet, dass wir benutzerdefinierte Elemente verwenden können, um Widgets für jede Webseite zu veröffentlichen. Aus diesem Grund solltest du den Referer Header bei jeder eingehenden Anfrage an die Komponente überprüfen, um eine unbefugte Nutzung zu verhindern.

In unserem Beispiel wird das benutzerdefinierte Element vom Entwicklungsserver von Preact bereitgestellt. Für eine Produktionsversion würdest du wahrscheinlich einen statischen Build der Komponente erstellen wollen, der wahrscheinlich deutlich kleiner sein wird.8

Du kannst den Quellcode für dieses Rezept von der GitHub-Seite herunterladen.

1.9 Storybook für die Komponentenentwicklung verwenden

Problem

React-Komponenten sind das stabile Baumaterial von React-Anwendungen. Wenn wir sie sorgfältig schreiben, können wir die Komponenten in anderen React-Anwendungen wiederverwenden. Aber wenn du eine Komponente baust, musst du überprüfen, wie sie unter allen Umständen funktioniert. In einer asynchronen Anwendung könnte React die Komponente zum Beispiel mit undefinierten Eigenschaften darstellen. Wird die Komponente trotzdem korrekt dargestellt oder werden Fehler angezeigt?

Wenn du aber Komponenten als Teil einer komplexen Anwendung baust, kann es schwierig sein, alle Situationen zu erstellen, mit denen deine Komponente zurechtkommen muss.

Wenn du in deinem Team spezialisierte User Experience (UX)-Entwickler/innen hast, kann es außerdem viel Zeit kosten, wenn sie durch eine Anwendung navigieren müssen, um eine einzelne Komponente zu sehen, die sie in der Entwicklung haben.

Es wäre hilfreich, wenn es eine Möglichkeit gäbe, eine Komponente isoliert darzustellen und ihr Beispielsätze von Eigenschaften zu übergeben.

Lösung

Storybook ist ein Werkzeug, mit dem du Bibliotheken von Bauteilen in verschiedenen Zuständen anzeigen kannst. Man könnte es als eine Galerie für Komponenten bezeichnen, aber das wäre wohl zu kurz gegriffen. In Wirklichkeit ist Storybook ein Werkzeug für die Komponentenentwicklung.

Wie fügen wir Storybook zu einem Projekt hinzu? Beginnen wir damit, eine React-Anwendung mit create-react-app zu erstellen:

$ npx create-react-app my-app
$ cd my-app

Jetzt können wir Storybook zu dem Projekt hinzufügen:

$ npx sb init

Dann starten wir den Storybook-Server mit yarn oder npm:

$ npm run storybook

Storybook führt einen separaten Server auf Port 9000 aus, wie du in Abbildung 1-11 sehen kannst. Wenn du Storybook verwendest, musst du die eigentliche React-Anwendung nicht ausführen.

Abbildung 1-11. Die Willkommensseite im Storybook

Storybook nennt eine einzelne Komponente, die mit Beispieleigenschaften gerendert wird, eine Story. Die Standardinstallation von Storybook erzeugt Beispielstories im Verzeichnis src/stories der Anwendung. Das ist zum Beispiel src/stories/Button.stories.js:

import React from 'react';

import { Button } from './Button';

export default {
  title: 'Example/Button',
  component: Button,
  argTypes: {
    backgroundColor: { control: 'color' },
  },
};

const Template = (args) => <Button {...args} />;

export const Primary = Template.bind({});
Primary.args = {
  primary: true,
  label: 'Button',
};

export const Secondary = Template.bind({});
Secondary.args = {
  label: 'Button',
};

export const Large = Template.bind({});
Large.args = {
  size: 'large',
  label: 'Button',
};

export const Small = Template.bind({});
Small.args = {
  size: 'small',
  label: 'Button',
};

Storybook sucht in deinem Quellordner nach Dateien mit dem Namen *.stories.js. Es ist egal, wo sie sich befinden, du kannst sie also dort anlegen, wo du willst. Ein typisches Muster ist, die Stories in einem Ordner neben der Komponente zu platzieren, die sie präsentieren. Wenn du also den Ordner in eine andere Anwendung kopierst, kannst du die Stories als lebendeDokumentation einbinden.

Abbildung 1-12 zeigt, wie Button.stories.js in Storybook aussieht.

Abbildung 1-12. Eine Beispielgeschichte

Diskussion

Trotz seines einfachen Aussehens ist das Storybook ein produktives Entwicklungswerkzeug. Es ermöglicht dir, dich jeweils auf eine Komponente zu konzentrieren. Wie eine Art visueller Unit-Test ermöglicht es dir, eine Komponente in einer Reihe von möglichen Szenarien auszuprobieren, um zu prüfen, ob sie sich angemessen verhält.

Storybook hat auch eine große Auswahl an zusätzlichen Add-ons.

Mit den Add-ons kannst du:

  • Prüfe auf Probleme mit der Barrierefreiheit(addon-a11y)

  • Interaktive Steuerelemente zum Einstellen von Eigenschaften(Knöpfe) hinzufügen

  • Füge Inline-Dokumentation für jede Story ein(Docs)

  • Zeichne Schnappschüsse von HTML auf, um die Auswirkungen von Änderungen zu testen(Storyshots)

Und noch viel mehr tun.

Weitere Informationen über Storybook findest du auf der Website.

Du kannst den Quellcode für dieses Rezept von der GitHub-Seite herunterladen.

1.10 Teste deinen Code in einem Browser mit Cypress

Problem

Die meisten React-Projekte enthalten eine Testbibliothek. Die gebräuchlichste ist wahrscheinlich @testing-library/react, die mitcreate-react-app mitgeliefert wird, oder Enzyme, das von Preact verwendet wird.

Aber nichts geht über das Testen von Code in einem echten Browser, mit all den zusätzlichen Komplikationen, die das mit sich bringt. Traditionell können Browsertests instabil sein und erfordern häufige Wartung, da du die Browsertreiber (wie den ChromeDriver) jedes Mal aktualisieren musst, wenn du den Browser aktualisierst.

Hinzu kommt das Problem, dass die Testdaten auf einem Backend-Server generiert werden müssen, und die Einrichtung und Verwaltung von browserbasierten Tests kann sehr komplex sein.

Lösung

Das Cypress-Testframework vermeidet viele der Nachteile herkömmlicher Browser-Tests. Es wird in einem Browser ausgeführt, ohne dass ein externes Web-Treiber-Tool benötigt wird. Stattdessen kommuniziert es direkt mit einem Browser wie Chrome oder Electron über einen Netzwerkport und fügt dann JavaScript ein, um einen Großteil des Testcodes auszuführen.

Lass uns eine Anwendung create-react-app erstellen, um zu sehen, wie sie funktioniert:

$ npx create-react-app --use-npm my-app

Jetzt lass uns in das App-Verzeichnis gehen und Cypress installieren:

$ cd my-app
$ npm install cypress --save-dev

Bevor wir Cypress starten, müssen wir es so konfigurieren, dass es weiß, wie es unsere Anwendung finden kann. Dazu erstellen wir einecypress.json-Datei im Anwendungsverzeichnis und teilen ihr den Uniform Resource Locator (URL) unserer Anwendung mit:

{
  "baseUrl": "http://localhost:3000/"
}

Sobald wir die Hauptanwendung gestartet haben:

$ npm start

können wir dann Cypress öffnen:

$ npx cypress open

Wenn du Cypress zum ersten Mal startest, installiert es alle benötigten Abhängigkeiten. Jetzt erstellen wir im Verzeichniscypress/integration einen Test namens screenshot.js, der die Startseite öffnet und einen Screenshot macht:

describe('screenshot', () => {
    it('should be able to take a screenshot', () => {
        cy.visit('/');
        cy.screenshot('frontpage');
    });
});

Du wirst feststellen, dass wir die Tests im Jest-Format geschrieben haben. Sobald du den Test speicherst, erscheint er im Hauptfenster von Cypress, wie inAbbildung 1-13 dargestellt.

Abbildung 1-13. Das Cypress-Fenster

Wenn du auf den Test doppelklickst, wird er von Cypress in einem Browser ausgeführt. Die Startseite der Anwendung wird geöffnet, und der Test speichert einen Screenshot unter cypress/screenshots/screenshot.js/frontpage.png.

Diskussion

Hier sind einige Beispielbefehle, die du mit Cypress ausführen kannst:

Befehl Beschreibung

cy.contains('Fred')

Findet das Element, das Fred

cy.get('.Norman').click()

Klickt das Element mit der Klasse Norman

cy.get('input').type('Hi!')

Gib "Hi!" in das Eingabefeld ein

cy.get('h1').scrollIntoView()

Blättert die <h1/> in die Ansicht

Dies sind nur einige der Befehle, die mit der Webseite interagieren. Aber Cypress hat noch einen weiteren Trick in petto. Cypress kann auch den Code innerhalb des Browsers verändern, um die Uhrzeit (cy.clock()), die Cookies (cy.setCookie()), die lokale Speicherung (cy.clearLocalStorage()) und - besonders beeindruckend - Anfragen und Antworten an einen API-Server zu fälschen.

Er tut dies, indem er die im Browser eingebauten Netzwerkfunktionen so verändert, dass dieser Code:

cy.route("/api/server?*", [{some: 'Data'}])

fängt alle Anfragen an einen Server-Endpunkt ab, der mit /api/server? beginnt, und gibt das JSON-Array[{some: 'Data'}] zurück.

Die Simulation von Netzwerkreaktionen kann die Art und Weise, wie Teams Anwendungen entwickeln, völlig verändern, weil sie die Frontend-Entwicklung vom Backend entkoppelt. Die Browser-Tests können angeben, welche Daten sie benötigen, ohne einen echten Server und eineDatenbank erstellen zu müssen.

Um mehr über Cypress zu erfahren, besuche die Dokumentationsseite.

Du kannst den Quellcode für dieses Rezept von der GitHub-Seite herunterladen.

1 Und ja, das bedeutet, dass Gatsby TypeScript-Unterstützung eingebaut hat.

2 In den meisten Betriebssystemen kannst du dies mit der Tastenkombination Strg-C tun.

3 Der Name ist absichtlich ähnlich wie create-react-app. Der Betreuer von Razzle, Jared Palmer, nennt create-react-app als eine der Inspirationen für Razzle.

4 Siehe Rezept 1.2.

5 Siehe Rezepte 1.2 und 1.3.

6 Weitere Informationen zur Erstellung von Preact-Anwendungen findest du in Rezept 1.5.

7 Weitere Einzelheiten zu benutzerdefinierten Elementen und Namenskonventionen findest du in der WHATWG-Spezifikation.

8 Weitere Informationen zum Verkleinern von Preact-Downloads findest du in Rezept 1.5.

Get React Kochbuch now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.