JavaScript-Frameworks: Gatsby, Next, Nest, Nuxt… Nust?

March 07, 2023
Autor:in:
Prüfer:in:
Paul Kamp
Twilion

Hallo und danke fürs Lesen! Dieser Blogpost ist eine Übersetzung von Next, Nest, Nuxt… Nust?.

Dieser Blogbeitrag ist für alle gedacht, die nach einem neuen Lieblings-JavaScript-Framework für ihr Backend suchen. Vor ein paar Monaten stand ich genau an diesem Punkt und wollte ein neues JavaScript-Backend-Framework für mein Nebenprojekt lernen.

Um ehrlich zu sein, war ich ein wenig überfordert mit all den vielversprechenden Optionen zur Auswahl. NextNestNuxt... Wenn Sie diese Bezeichnungen hören, glauben Sie wahrscheinlich, dass der JavaScript-Community nun endgültig die Namen ausgegangen sind und „Nust“ jetzt der nächste große Wurf ist. Der erste Punkt auf meiner To-Do-Liste war also, das beste Framework für mein Nebenprojekt zu finden.

Wenn auch Sie die Frameworks Gatsby, Next.js, Nest und NuxtJS besser verstehen möchten, ist dieser Beitrag genau für Sie geschrieben. Ich werde über die Ähnlichkeiten und Unterschiede zwischen den Frameworks, über ihre Leistungsmerkmale und ihre Beliebtheit in der Praxis sprechen und darüber, wie Sie das beste Modell für Ihre Zwecke auswählen.

Fangen wir an.

Express versus Next.js, Nest, Gatsby oder Nuxt

Alle diese Open-Source-Frameworks sind laut der aktuellen „State of JavaScript“-Umfrage die beliebtesten Backend-Frameworks. Laut der „State of JS“-Umfrage gehören Next.js, Gatsby, NuxtJS und Nest zu den Top 5. Sie stehen hinter der bisher ungeschlagenen Nummer Eins, Express, und wachsen weiter. Aber was steckt eigentlich hinter ihnen?

Ergebnisse der StateOfJSUmfrage

Express gibt es fast schon seit der Einführung von Node.js und ist de facto das Standard-JavaScript-Framework. Es ist relativ nah am HTTP-Protokoll und bietet eine minimalistische Schnittstelle, was erklärt, warum es häufig als Basis für viele andere Frameworks verwendet wird. Die anderen Frameworks der Top 5 folgen einer ganz anderen Strategie und bieten ihren Nutzer:innen sehr viele Abstraktionen. Diese Abstraktionen erfordern allerdings auch ein tieferes Verständnis der Frameworks selbst. In diesem Beitrag stelle ich Ihnen die anderen Mitstreiter unter den Top 5 der am häufigsten genutzten Frameworks vor: Gatsby, Next.js, NuxtJS und Nest.

Die folgenden beiden Abschnitte behandeln Web Vitals wie LP und LCP sowie Rendering-Strategien wie CSR, SSR und isomorphe Anwendungen. Wenn Sie diese Abkürzungen bereits kennen, können Sie diese Abschnitte überspringen und direkt zum nächsten Abschnitt “Frameworks” gehen.

Leistungsmetriken für Webanwendungen

Bevor wir näher in die Frameworks eintauchen, sollten wir uns mit den Anforderungen für Webanwendungen befassen. Fast alle Projekte haben ein Ziel gemeinsam: relevante, hochwertige Inhalte für Ihre Nutzer:innen bereitzustellen. Wir wissen aber auch, dass selbst die besten Inhalte allein nicht reichen. Sie müssen in einer akzeptablen Ladezeit dargestellt werden und (sofern es um öffentliche Inhalte geht) überhaupt auffindbar sein.

Der letztgenannte Punkt der Auffindbarkeit ist schnell erklärt. Wenn Sie Inhalte auf einer öffentlichen Website veröffentlichen, sollen Suchmaschinen die Seite indizieren, damit sie dann in den Suchergebnissen auftauchen kann.

Der Leistungsaspekt ist vielleicht etwas schwieriger zu definieren: Welche Leistungskennzahl gibt an, dass der Inhalt zeitig präsentiert wird? Vermutlich lässt sich diese Frage nicht endgültig beantworten. Aber es gibt sicherlich mehrere brauchbare Kennzahlen, die in der Kombination ein ganzheitliches Bild ermöglichen:

  • Time to First Byte (TTFB)
    Die Metrik TTFB bemisst die Zeit, bis das erste Byte einer HTTP-Antwort empfangen wird. Mit dieser Metrik kann die Last auf dem Server und dem Netzwerk zwischen Client und Server bewertet werden.
  • First Paint (FP)
    Zeitspanne, bis ein beliebiges Pixel für die Nutzer:innen sichtbar wird. Dies beinhaltet TTFB und die Berechnung, die der Client für das initiale Rendering der Webseite durchführen muss.
  • First Contentful Paint (FCP)
    Die Zeitspanne, bis der erste Text oder das erste Bild sichtbar wird. Diese ähnelt der FP, ist aber ein weniger technisches Maß und definiert die Rendering-Phase, die den Nutzer:innen zeigt, dass die Seite funktioniert.
  • Largest Contentful Paint (LCP)
    Die Zeitspanne, bis die komplette Seite für Nutzer:innen sichtbar wird. Diese Metrik könnte auch als die Zeit beschrieben werden, bis Nutzer:innen das erwartete Ergebnis sehen.
  • Time to Interactive (TTI)
    Die Zeitspanne, bis die Seite vollständig interaktiv ist. Nutzer:innen könnten dies zum gleichen Zeitpunkt wie die LCP erwarten, aber der Zeitpunkt kann auch abweichen. Das Abweichen von TTI und LCP kann Nutzer:innen verwirren und dazu führen, dass sie glauben, die Webseite sei beschädigt.

Ergebnisse eines Lighthouse performance Tests in Chrome

Diese Kennzahlen wurden vom Chrome-Team eingeführt und werden oft auch als Web Vitals bezeichnet. Die gute Nachricht ist, dass alle Blink-basierten Browser mit Entwicklungstools zur Messung dieser Metriken ausgestattet sind. Die schlechte Nachricht ist, dass Safari diese Metriken derzeit nicht unterstützt. Sie müssen also möglicherweise andere Browser für die Leistungsoptimierung verwenden, andere Metriken in diesen Browsern verwenden oder sich mit einer Stoppuhr vor den Bildschirm setzen. 🙂

Aber keine Sorge. Für diesen Beitrag spielt es keine Rolle, welchen Browser Sie verwenden, da wir anhand dieser Metriken im nächsten Abschnitt nur die Unterschiede zwischen den verschiedenen Rendering-Optionen hervorheben wollen.

Rendering-Optionen

Sehr allgemein betrachtet, funktionieren alle Webseiten gleich. Der Client sendet eine erste Anfrage an den Server, auf dem die gewünschten Informationen liegen. Der Server antwortet mit der angefragten Datei, die gegebenenfalls eine Kaskade weiterer Anfragen des Client’s auslöst. Am Ende verfügt der Client über alle benötigten Daten und zeigt eine Seite, die die Informationen visuell für die Nutzer:innen darstellt.

Visualisierung des Client-Server-Flows

Für statische Inhalte, also Inhalte, die für alle Nutzer:innen gleich aussehen und keine Berechnung erfordern, werden HTML- und CSS-Dateien auf dem Server gespeichert und dem Client auf Anfrage geliefert. Der Client, in den meisten Fällen der Browser, analysiert diese Dateien und erstellt das DOM (Document Object Model) auf Grundlage dieser Anweisungen.

“Leider” bestehen große Teile des Webs aus dynamischen Inhalten, die für alle Nutzer:innen unterschiedlich sein müssen, möglicherweise sogar abhängig von der Zeit oder dem Status beim Zugriff der Nutzer:innen. Und für diese Szenarien müssen während des oben visualisierten Prozesses Berechnungen erfolgen.

Als ich lernte zu Programmieren, waren Java Servlets ein beliebter Ansatz, um Websiten dynamische Inhalte hinzuzufügen. Immer wenn eine Anfrage den Server erreichte, wurde ein kompilierter Java-Bytecode ausgeführt, der die HTML-Antwort auf die Anfrage ausgab. Nach dem Aufkommen von Frameworks wie AngularJSBackbone.js und Knockout im Jahr 2010 konnte man dann eine Verlagerung zu SPA (Single Page Applications) beobachten.

Beim SPA-Ansatz werden hauptsächlich JS- und JSON-Dateien zwischen Client und Server übertragen. Bei der Ausführung dieser Dateien im Browser werden dynamisch DOM-Elemente erstellt, bis die Nutzer:innen die fertige Webseite sehen. Java Servlets und Single Page Apps führen Code aus, um das Markup der Website zu generieren. Sie unterscheiden aber darin, wo und wann sie diesen Code ausführen. Oder anders gesagt, welche Rendering-Strategie sie verwenden.

Verschiedene Rendering-Strategien haben Vor- und Nachteile, je nachdem, was Ihre Anforderungen sind. Manche werden für Ihr Projekt relevanter sein als andere. In den folgenden Abschnitten behandeln wir die derzeit häufigsten von ihnen.

Clientseitiges Rendering (CSR)

Anwendungen, die die einzelnen Seiten alle im Browser des Clients rendern (berechnen), werden oft auch als Single Page Applications bezeichnet. Dieses Konzept ist auch als clientseitiges Rendering (CSR) bekannt.

Der Server liefert im Wesentlichen den minifizierten JavaScript-Code, der auf Clientseite ausgeführt wird, um zusätzliche Informationen via HTTP-Anfragen zu senden und die DOM-Elemente zu rendern. Für viele Webentwickler ist dies aktuell der de facto Standard für die Entwicklung von Webanwendungen. Beliebte SPA-Frameworks sind ReactAngularVue.js und Svelte.

Dieser Ansatz hat den Vorteil, dass er sich gut skalieren lässt, denn der Großteil der Berechnung erfolgt auf dem Client. Dies ist auch der Grund dafür, dass TTFB, die Zeit bis zum Empfang des ersten Byte, recht schnell ist. Ein weiterer Vorteil ist, dass Sie moderne Web-APIs, wie GeolocationClipboard oder Push,verwenden können.

Es gibt jedoch auch Nachteile. Da das gesamte Rendering auf dem Client geschieht, benötigt dies zusätzliche Zeit nachdem die JavaScript-Dateien geladen wurden. Während dieser Zeit ist die Benutzeroberfläche blockiert und die Webseite nicht nutzbar. Diese zusätzliche Zeit verlängert auch Metriken wie First Paint, First Contentful Paint, Largest Contentful Paint und Time-to-Interactive. Um diese Wartezeit zu kompensieren, erstellen Frontend-Entwickler häufig Ladebildschirme oder Splash-Screens, die die wahrgenommene Ladezeit, sowie FC und FCP, verkürzen. Ein weiterer Nachteil ist, dass die meisten Suchmaschinen JavaScript nicht ausführen. Das führt zu Problemen, wenn Sie an der SEO (Suchmaschinenoptimierung) interessiert sind. Da Crawler den Seiteninhalt nur schwer verstehen können, kann es die Auffindbarkeit Ihrer Seiten beeinträchtigen. Aber es gibt natürlich auch Projekte, wie unternehmensinterne Apps, bei denen SEO nicht relevant ist und dieser Aspekt nicht weiter stört.

Serverseitiges Rendering (SSR)

Ein anderer Ansatz, das serverseitige Rendering (SSR), berechnet die vollständige Seite, bevor die eingehende Anfragen beantwortet wird. Dieser Rendering-Ansatz ist in vielerlei Hinsicht das Gegenteil von clientseitigem Rendering. Da Suchmaschinen-Crawler die Webseiten leicht auslesen können, ist dieser Ansatz SEO-freundlich. Außerdem sind die Inhalte immer aktuell und können an die Nutzer:innen angepasst werden. First Paint, First Contentful Paint, Largest Contentful Paint und Time to Interactive sind schnell und in der Regel sehr nah beieinander.

Wie Sie sich vorstellen können, gibt es aber auch hier einen Nachteil. Da Server die Berechnungen erst abschließen müssen, bevor sie das Markup bereitstellen, ist die Time To First Byte in der Regel länger.

Dieser Ansatz ist vergleichsweise schwer zu skalieren, da die Rechenlast stark mit der Zahl der Nutzer:innen zunimmt. Webseiten, die für alle Nutzer:innen sehr ähnlich aussehen, sind hier sehr ineffizient, da dieselben Berechnungen mit denselben Ergebnissen wiederholt durchgeführt werden.

Static-Site-Generierung (SSG)

Die SSG oder Static-Site-Generierung berechnet das Markup während die Webanwendung “kompiliert” wird, statt auf Abruf. Dieser Ansatz konzentriert sich auf die Reduzierung wiederholter serverseitiger Berechnungen, indem statistische Webseiten im Voraus berechnet werden. Diese Berechnung verlängert den Compilezeit der Serveranwendung, spart aber schließlich Rechenzeit während der Laufzeit.

Alle Metriken (Time to First Byte, First Paint, First Contentful Paint, Largest Contentful Paint und Time to Interactive) profitieren von diesem Ansatz, da er der statischen Bereitstellung von Inhalten sehr ähnlich ist. Dies führt auch zu niedrigeren Serverkosten und ausgezeichneter Skalierbarkeit.

Der große Nachteil ist, dass alle Seiten für alle Nutzer:innen gleich aussehen. Das ist nur bei einigen Arten von Webanwendungen gewünscht oder überhaupt möglich. Oder können Sie sich einen Webshop vorstellen, insbesondere den Inhalt des Warenkorbs, der für alle Nutzer:innen gleich aussieht? Für einige Seiten, wie z. B. API-Dokumentation oder kleine Blogs, können Entwickler sich diese Rendering-Strategie sehr gut zunutze machen.

Aber das Beispiel eines „statischen Webshops“ zeigt einen zweiten Nachteil:
Jedes Mal, wenn sich ein Artikel ändert, muss die komplette Website neu gebaut werden. Sie müssten die gesamte Anwendung neu berechnen, um eine einzelne Produktbeschreibung zu aktualisieren. Andernfalls würde der Shop nie die neuesten Informationen anzeigen. Bei der Static-Site-Generierung ist es also sinnvoll, die Strategie ein wenig zu modifizieren und Seiten entweder ablaufen zu lassen oder erst zu rendern, wenn sie zum ersten Mal angefragt werden. Diese Modifikationen werden als Incremental Static Regeneration (ISR) bzw. Deferred Site Generation (DSG) bezeichnet.

Hybride Rendering-Strategien – universelle/isomorphe Anwendungen, Hydration und clientseitiger Abruf

Reinformen der zuvor erwähnten Strategien verschieben die gesamte Rechenlast zum Client, Server bzw. Build-Server. Die Nebenwirkungen sind dann die aufgeführten Vor- und Nachteile, wie SEO-freundliche Seiten vs. Seiten ohne SEO-Unterstützung. Aber so muss es nicht sein. Warum nicht einen Teil der Berechnung auf dem Client und andere Teile auf einem Server durchführen?

Für eine bessere Auffindbarkeit scheint es sinnvoll, die Anzahl der clientseitig gerenderten Seitenelemente zu minimieren. Das heißt, wir wollen nur benutzerspezifische Elemente im Browser rendern. Alle anderen Seitenelemente, wie Kopfzeilen, Fußzeilen, Seitenleisten oder auch ganze Seiten wie „Über uns“, können auf dem Server gerendert und zwischengespeichert werden, um Zeit zu sparen.

Dieser Ansatz wird in den verschiedenen Frameworks unterschiedlich bezeichnet. Einige beschreiben diese Arten von Anwendungen als universell oder isomorph. Andere Frameworks bezeichnen den Prozess als (Re-)Hydration oder ”client-side Fetching”. Vielleicht stoßen Sie auch auf den Begriff Pre-Rendering. Den vermeide ich aber, weil er nicht klar definiert ist.

Ein Hinweis zum Begriff Pre-Rendering:

Auf diesen Begriff werden Sie häufig stoßen, wenn Sie sich über Rendering-Optionen informieren. Auch wenn er auf den ersten Blick gut zu passen scheint, versuche ich ihn zu vermeiden, weil ich noch keine klare Definition dafür gefunden habe.

In einem Blog-Beitrag sagen Software Engineers von Chrome und Shopify, es gibt einen Unterschied zwischen statischem Rendering und Pre-Rendering. Laut der Vue.js-Dokumentation wird die Static-Site-Generierung (SSG) allerdings auch als Pre-Rendering bezeichnet. Die Next.js-Dokumentation besagt außerdem, Static-Generation- und serverseitiges Rendering seien zwei Formen des Pre-Renderings. Die Jamstack-Dokumentation folgt einer ähnlichen Idee, allerdings bezeichnet sie alles, was direkt von einem CDN aus bedient werden kann, als Pre-Rendering. Dazu gehören Static-Site-Standortgenerierung, serverseitiges Rendering und der Hybridansatz.

Diese Meinung teile ich auch: Pre-Rendering ist alles, was nicht ausschließlich auf der Clientseite gerendert wird. Aber da ich nicht noch mehr Verwirrung stiften möchte, vermeide ich den Begriff (zumindest vorerst).

Unabhängig von ihrem Namen bietet diese Strategie eine schnelle Time to First Byte, First Paint und First Contentful Paint und ist zudem SEO-freundlich. Nur im Hinblick auf Largest Contentful Paint und Time To Interactive zeigt sich in der Regel ein Nachteil. Insgesamt sind diese Metriken jedoch immer noch besser als bei Single Page Apps, die nur auf dem Client gerendert werden.

In Bezug auf die Web Vital-Metriken dieses Ansatzes gibt es keinen echten Nachteil, aber einen praxisbezogenen Aspekt. Er ist mit der zusätzlichen Komplexität verbunden. Es liegt nämlich an uns Entwicklern, um zu definieren, wann welche Seitenelemente wo gerendert werden sollen.

Mehrere Rendering-Strategien

Sie sehen, es gibt viele Rendering-Strategien, aus denen Sie wählen können. Und ehrlich gesagt, sind diese Klassifizierungen alle eher theoretischer Art. Im wahren Leben kann eine Website mehrere Strategien für verschiedene Unterseiten verwenden. Um beim Beispiel eines Webshops zu bleiben, müssen der Katalog und die Produktseiten eine kurze Ladezeit haben und gleichzeitig SEO-optimiert sein. Das klingt nach einem Job für die Static-Site-Generierung. Es werden jedoch auch einige nutzerspezifische Seiten benötigt, bei denen SEO kein Faktor ist, wie z. B. der Warenkorb. Für diese Unterseiten ist eine hybride Rendering-Strategie sinnvoll. Das Layout der Warenkorbseite, das für alle Nutzer:innen gleich ist, kann auf dem Server gerendert werden, während die Elemente des Warenkorbs mittels clientseitigem Abruf später hinzugefügt werden können.

Wenn Sie eine Web-App implementieren, die teilweise auf dem Client und teilweise auf dem Server gerendert wird, wie entscheiden Sie, welcher Code auf welcher Plattform ausgeführt werden muss oder wie der Code minifiziert und in einzelne Abschnitte aufgeteilt wird? Das kann sehr schnell kompliziert werden. Glücklicherweise gibt es Frameworks, die Ihnen hierbei helfen können.

Frameworks

Gatsby

Gatsby wurde 2015 zunächst als Framework für die Static-Site-Generierung von React-Webanwendungen konzipiert. Im Laufe der Zeit wurden einige weitere Rendering-Optionen ergänzt, wie Deferred Site Generation (bei der ersten Anfrage), serverseitiges Rendering (das Sie nur in einigen Fällen verwenden sollten) und client-side fetching.

Sie können die Daten, die für die Webseite nötig sind, aus mehreren Systemen, wie CMS oder Datenbankmanagementsystemen, laden.  GraphQL ist eine Technologie, die fundamental mit Gatsby’s Philosophie verbunden ist. Das Framework umfasst einen eigenen GraphQL-Server, der Metadaten über den Server und verbundenen Datenquellen liefert.

Ein besonderes Highlight dieses Frameworks ist die Größe der Open-Source-Community, die eine umfangreiche Plug-in-Bibliothek aufgebaut hat. Mit dieser Bibliothek können Sie auf die jahrelange Erfahrung von Gatsbyexperten innerhalb weniger Minuten zugreifen und diese für Ihre Projekte nutzen.

So könnte eine Gatsby 404-Seite aussehen:

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


const pageStyles = {
 color: "#232129",
 padding: "96px",
 fontFamily: "-apple-system, Roboto, sans-serif, serif",
}
const headingStyles = {
 marginTop: 0,
 marginBottom: 64,
 maxWidth: 320,
}

const paragraphStyles = {
 marginBottom: 48,
}
const codeStyles = {
 color: "#8A6534",
 padding: 4,
 backgroundColor: "#FFF4DB",
 fontSize: "1.25rem",
 borderRadius: 4,
}

const NotFoundPage = () => {
 return (
   <main style={pageStyles}>
     <h1 style={headingStyles}>Seite nicht gefunden</h1>
     <StaticImage alt="Clifford, ein Pitbull"
       src="https://pbs.twimg.com/media/E1oMV3QVgAIr1NT?format=jpg&name=large"
     />

     <p style={paragraphStyles}>
       Entschuldigen Sie 😔, wir konnten Ihre Seite nicht finden.
       <br />
       <Link to="/">Zur Startseite</Link>.
     </p>
   </main>
 )
}

export default NotFoundPage

Mit seinen unterstützten Rendering-Optionen ist Gatsby gut dafür gerüstet, Jamstack-Seiten zu implementieren. Hier habe ich eine großartige Ressource zu Jamstack für Sie. Sie erläutert die Vorteile von Anwendungen, die Daten und Geschäftslogik von der Präsentationslogik abkoppeln. Webseiten, die mit Gatsby erstellt werden, stellen meist Informationen bereit, wobei die Nutzer:innen wenig eigene Inhalte erstellen können. Dies ist beispielsweise für Web-Auftritte von Unternehmen sehr hilfreich.

Das Framework bietet Entwicklern allerdings nicht die Möglichkeit, eigene Backend-Logik zu implementieren. Sollten Sie diese benötigen, könnte ein Framework wie Next.js für Sie interessant sein.

Next.js

Das Next.js-Framework, erstmals 2016 veröffentlicht, ähnelt in vieler Hinsicht Gatsby und ist ebenfalls React-basiert. Allerdings  enthält es einigen zusätzlichen Edge-Computing-Funktionen. Zu diesen Funktionen gehören Edge-Functions, die serverlose Ausführung von Code und Edge Middleware, die bestimmte Anfragen an andere Domänen umleitet. So können Sie Ihre serverlose Next.js-App global ausführen, ohne sich Gedanken über die Serververwaltung machen zu müssen.

Eine Startseite in Next.js könnte wie folgt aussehen:

import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'

export default function Home() {
 return (
   <div className={styles.container}>
     <Head>
       <title>Meine Next App</title>
       <link rel="icon" href="/favicon.ico" />
     </Head>

     <main className={styles.main}>
       <h1 className={styles.title}>
         Welcome to <a href="https://nextjs.org">Next.js!</a>
       </h1>

       <p className={styles.description}>
         Lege los indem du{' '} 
         <code className={styles.code}>pages/index.js</code>{' '}
         bearbeitest
       </p>
     </main>

     <footer className={styles.footer}>
       <a
         href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
         target="_blank"
         rel="noopener noreferrer"
       >
         Powered by{' '}
         <span className={styles.logo}>
           <Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
         </span>
       </a>
     </footer>
   </div>
 )
}

Eine Edge-Function:

const twilio = require("twilio");

export default function handler(req, res) {
 const twiml = new twilio.twiml.MessagingResponse();
 twiml.message("Hi, ich bin eine TwiML Antwort");
 res.setHeader("Content-Type", "text/xml");
 res.status(200).send(twiml.toString());
}

Einzigartige Merkmale von Next.js sind seine große Beliebtheit, seine große Community und die weit verbreitete Nutzung. Das Framework unterstützt sowohl die Bereitstellung auf Ihrer eigenen Infrastruktur als auch in mehreren Edge-Netzwerken, um Serververwaltungsaufgaben auszulagern.

Next.js unterstützt Static-Site-Generierung, serverseitiges Rendering, Incremental Static Regeneration und das Client-Side Fetching. Damit ist es für dieselben Anwendungsfälle wie Gatsby geeignet, unterstützt aber deutlich mehr Datenquellen. Außerdem kann es für Anwendungen, die mit einer minimalen Backend-Logik auskommen, ebenfalls genutzt werden.
Andererseits kann diese serverlose Natur von Next.js auch einen Nachteil darstellen. Es gibt keine Möglichkeit, einen Zustand zu sichern oder zu verwalten.

NuxtJS

NuxtJS, das erstmals 2016 veröffentlicht wurde, unterscheidet sich von den oben genannten Frameworks in vielerlei Hinsicht. Der offensichtlichste Unterschied ist der, dass Sie nicht mit React arbeiten, sondern mit einem anderen beliebten UI-Framework: Vue.js Das heißt jedoch nicht, dass NuxtJS ein Port von Next.js ist. NuxtJS ist ganz anders konzipiert und bietet alle Rendering-Optionen, auch clientseitiges Rendering. Daher kann dieses Framework auch für Progressive Web Apps (PWA) verwendet werden.

Darüber hinaus bietet es einen umfangreichen Wizard, der Sie durch unterschiedliche Konfigurationen, Test-Bibliotheken, Build-Bibliotheken und Komponentenpakete führt. Es lässt sich also auch als Framework für Frameworks betrachten. Zudem verfügt NuxtJS über eine Funktion zur Zustandsspeicherung: den Vuex Store.

Eine NuxtJS-Seitendefinition könnte wie folgt aussehen:

<template>
 <div>
   <h1>Hallo Nuxters! 👋</h1>
   <p>
     Diese Seite wurde auf dem <strong>{{ rendering }}</strong> gerendert.
   </p>
   <p v-if="rendering === 'Server'">
     Das initiale Laden findet auf dem Server statt.
   </p>
   <p v-if="rendering === 'Client'">Navigation wird im Browser verarbeitet.</p>
   <ul>
     <li>Lade die Seite neu für server-seitiges Rendering.</li>
     <li>Klicke die Links um client-seitiges Rendering zu sehen.</li>
   </ul>

   <NuxtLink to="/about">Über uns</NuxtLink>
 </div>
</template>
<script>
export default {
 asyncData() {
   return {
     rendering: process.server ? 'Server' : 'Client'
   }
 }
}
</script>

NuxtJS kann damit für die Entwicklung vieler Websiten verwendet werden. Das macht es jedoch nicht zu einem Framework zur Erstellung eigener Serveranwendungen, die neben HTTP auch andere Protokolle verarbeiten oder  Object Relational Mappers (ORM) beinhalten müssen.

Um diese ähnlich klingenden Frameworks zu unterscheiden, finde ich diese Eselsbrücke hilfreich: Next.js verwendet React, NuxtJS verwendet Vue.js.

 

Nest

Nest, das von Angular inspirierte Framework aus dem Jahr 2018, ist der eigentliche Ausreißer in dieser Reihe. Während alle anderen Frameworks verschiedene Rendering-Strategien implementieren, lebt Nest in einer anderen Sphäre abseits der Frontends. Dieses Framework für serverseitige Anwendungen ähnelt eher dem berühmten Spring Framework und lässt sich zur Implementierung von Microservices einsetzen. Es unterstützt nahezu alle gängigen Datenbankverwaltungssysteme über Object Relational Mapper und viele Protokolle jenseits von HTTP, wie z. B. WebSockets, GraphQL und MQTT.

Unter der Motorhaube von Nest sitzt Express. Zusätzlich bietet es jedoch auch Kompatibilität mit einer Vielzahl anderer Bibliotheken, wie Fastify, und ermöglicht so die bequeme Verwendung von Drittanbieter-Plug-ins. Mein Lieblings-Feature ist aber der saubere Mechanismus zur Code-Wiederverwendung mithilfe von Modulen. Mit Modulen können Sie Funktionen auslagern, die Sie in mehreren Teilen Ihrer Anwendung wiederverwenden oder aber für die gesamte Nest-Community als Bibliotheken freigeben können.

Beispiel einer Modulverwendung innerhalb einer Nest-Anwendung:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from "@nestjs/config";

@Module({
 imports: [ConfigModule.forRoot()],
 controllers: [AppController],
 providers: [AppService],
})
export class AppModule {}

Man muss sich vor Augen halten, dass dieses Framework nicht standardmäßig mit einem Frontend-Framework verbunden ist. Das bedeutet, dass Sie den dist-Ordner Ihres Frontend-Projekts manuell in dieses Projektverzeichnis integrieren (oder besser: dies in Ihrem Build-Skript automatisieren) müssen.

Solche Arten von Anwendungen müssen oft komplexere Berechnungen bewältigen und führen somit zu einer höheren Serverlast und sind unter Umständen schwerer zu skalieren.

Popularität in der Praxis

Das Ranking der „State of JS“-Umfrage zu Nutzung/Bewusstsein unterliegt einer Stichprobenverzerrung und spiegelt deshalb nicht unbedingt die Realität wider. Deshalb habe ich mir einige quantitative Daten angesehen, die etwas über die Erfahrungen von Entwickler:innen mit diesen Frameworks aussagen.

Ich habe die Download-Zahlen von npm sowie einige Community-Statistiken von GitHub und Stack Overflow geprüft. Diese Daten sind mit Stand Dezember 2022 als genau anzusehen.

Next.jsGatsbyNuxtJSNest
Nutzung / Bekanntheit#2#3#4#5
Wöchentliche Downloads3.5m412k485k1,9m
GitHub-Sterne97,7k53,9k10,9k *52,8k
GitHub-Forks21,6k10,5k1,1k *6,3k
GitHub-Beitragende2,4k3,9k340 *350
Stack Overflow-Fragen (beantwortet)25k (12,3k)5,6k (3,7k)10,9k (5,7k)9,8k (5,1k)

* Es wurde ein neues Repository für Version 3 gestartet und liegt daher etwas zurück

Bei fast all diesen Kennzahlen sehen wir, dass Next.js führend ist. Es hat die meisten Downloads, GitHub-Sterne und -Forks und verfügt über eine äußerst umfassende Wissensbasis auf Stack Overflow. Überraschenderweise hat Gatsby die meisten GitHub-Beiträge, was für die Größe seines Ökosystems spricht. Ebenso überraschend erscheint es, dass Nest so viele wöchentliche Downloads im Vergleich zu Gatsby und NuxtJS hat, auch wenn die anderen Statistiken sehr ähnlich sind. Eine mögliche Erklärung könnte sein, dass Nest das einzige der genannten Frameworks ist, das zur Implementierung von Backend-Servern genutzt werden kann, und insofern, in diesem Vergleich, ohne Konkurrenz dasteht. Die anderen Frameworks sind zwar nicht frei austauschbar, aber sie können alle für Server-gerenderte HTML-Seiten verwendet werden und machen sich dadurch gegenseitig Konkurrenz.

Kriterien für Ihre Auswahl

Jetzt, da wir mehr über diese Frameworks wissen, kommen wir nochmal auf den Anfang dieses Beitrags zurück. Welches Framework wäre für ein Implementierungsprojekt am besten geeignet? Um diese Frage zu beantworten, müssen Sie sich die folgenden Fragen stellen:

  • Möchten Sie eine Full-Stack-App erstellen oder nicht?
  • Falls ja: Möchten Sie mehr Freiheit und Flexibilität oder bevorzugen Sie die gebrauchsfertigen Module – sofern erhältlich –, die Sie nur anschließen müssen, um zum gewünschten Ergebnis zu kommen?
  • Falls die App keine Full-Stack-Entwicklung erfordert: Welche Rendering-Strategie bevorzugen Sie vor dem Hintergrund von Ladezeit und SEO-Freundlichkeit?

Dieser Entscheidungsbaum umfasst diese Fragen und hilft Ihnen, die Auswahl der vorgestellten Frameworks einzugrenzen:

Entscheidungsbaum für die Frameworks

Meine Empfehlungen und was als Nächstes kommt

Wenn Sie etwas Neues lernen möchten, empfehle ich Ihnen, sich mit Next.js zu befassen. Es eignet sich hervorragend, wenn Sie eine Website erstellen möchten, die React nutzt und einen informativen Charakter hat, ohne viel Interaktivität bieten zu müssen, wie z. B. eine Unternehmenswebsite, ein Blog oder eine Landing-Page für ein Produkt. Wenn Sie eine solche Website erstellen möchten, aber Vue.js bevorzugen, dann ist NuxtJS Ihr Kandidat.

Sie können auch ein SPA ohne Backend-Framework mit React oder Vue.js erstellen, wenn das für Ihre Anforderungen ausreicht. Wenn Sie hingegen eine Serveranwendung erstellen möchten, ist es sinnvoll zu erwägen, ob Sie mit vorgefertigten Modulen mit Plug-and-Play-Mechanismus (Nest) arbeiten oder mit Express alles selbst erstellen möchten.

Wenn Sie vorhaben, eines dieser Frameworks für Ihre Entwicklungen zu nutzen, können Sie mich bei offenen Fragen über einen der nachstehenden Kanäle kontaktieren.