Wie man eine fast Headless WordPress Website baut

Avatar of Alex Standiford
Alex Standiford am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Ich glaube, dass ein traditionelles WordPress-Theme genauso effektiv funktionieren sollte wie eine statische Website oder eine Headless-Webanwendung. Die überwiegende Mehrheit der WordPress-Websites wird mit einem altmodischen WordPress-Theme erstellt. Die meisten davon verfügen sogar über gute Caching-Layer und Abhängigkeitsoptimierungen, die diese Websites einigermaßen schnell laufen lassen. Aber als Entwickler haben wir Wege gefunden, bessere Ergebnisse für unsere Websites zu erzielen. Die Verwendung eines Headless WordPress hat es vielen Websites ermöglicht, schnellere Ladezeiten, bessere Benutzerinteraktionen und nahtlose Übergänge zwischen Seiten zu erzielen.

Das Problem? Wartung. Lassen Sie mich Ihnen eine weitere Möglichkeit zeigen!

Beginnen wir damit, was ich unter „traditionellem“ WordPress, „Headless“ WordPress und dann „Fast Headless“ WordPress verstehe.

Traditionelle WordPress-Websites

Traditionell wird eine WordPress-Website mit PHP erstellt, um das HTML-Markup zu rendern, das auf der Seite dargestellt wird. Jedes Mal, wenn auf einen Link geklickt wird, sendet der Browser eine weitere Anfrage an den Server, und PHP rendert das HTML-Markup für die angeklickte Website.

Dies ist die Methode, die die meisten Websites verwenden. Sie ist am einfachsten zu warten, hat die geringste Komplexität in der Technik und kann mit den richtigen serverseitigen Caching-Tools recht gut funktionieren. Das Problem ist, dass sie sich, da es sich um eine traditionelle Website handelt, auch wie eine traditionelle Website anfühlt. Übergänge, Effekte und andere stilvolle, moderne Features sind bei dieser Art von Website oft schwieriger zu erstellen und zu warten.

Pro

  1. Die Website ist einfach zu warten.
  2. Die Technik ist relativ einfach.
  3. Es gibt eine große Kompatibilität mit WordPress-Plugins.

Contra

  1. Ihre Website kann sich etwas veraltet anfühlen, da die Gesellschaft in der heutigen Zeit App-ähnliche Erlebnisse im Browser erwartet.
  2. JavaScript ist tendenziell etwas schwieriger zu schreiben und zu warten, da die Website kein JavaScript-Framework zur Steuerung des Website-Verhaltens verwendet.
  3. Traditionelle Websites sind tendenziell langsamer als Headless- und Fast-Headless-Optionen.

Headless WordPress-Websites

Eine Headless WordPress-Website verwendet modernes JavaScript und eine Art serverseitigen RESTful-Service, wie die WordPress REST API oder GraphQL. Anstatt das HTML in PHP zu erstellen und zu rendern, sendet der Server minimales HTML und eine große JavaScript-Datei, die das Rendern jeder Seite auf der Website übernehmen kann. Diese Methode lädt Seiten viel schneller und eröffnet die Möglichkeit, wirklich coole Übergänge zwischen Seiten und andere interessante Dinge zu schaffen.

Egal, wie man es dreht, die meisten Headless WordPress-Websites erfordern einen Entwickler vor Ort, um wesentliche Änderungen an der Website vorzunehmen. Möchten Sie ein Formular-Plugin installieren? Tut mir leid, Sie brauchen wahrscheinlich einen Entwickler, um das einzurichten. Möchten Sie ein neues SEO-Plugin installieren? Nein, Sie brauchen einen Entwickler, um die App zu ändern. Möchten Sie diesen schicken Block verwenden? Schade – Sie brauchen zuerst einen Entwickler.

Pro

  1. Die Website selbst wird sich modern und schnell anfühlen.
  2. Sie lässt sich leicht mit anderen RESTful-Diensten außerhalb von WordPress integrieren.
  3. Die gesamte Website ist in JavaScript erstellt, was die Erstellung komplexer Websites erleichtert.

Contra

  1. Sie müssen viele Dinge neu erfinden, die WordPress-Plugins standardmäßig für Sie erledigen.
  2. Diese Einrichtung ist schwer zu warten.
  3. Im Vergleich zu anderen Optionen ist das Hosting komplex und kann teuer werden.

Siehe „WordPress und Jamstack“ für einen detaillierteren Vergleich der Unterschiede zwischen WordPress und statischem Hosting.

Ich liebe das Ergebnis, das Headless WordPress erzielen kann. Ich mag die Wartung nicht. Was ich möchte, ist eine Webanwendung, die mir schnelle Ladezeiten, Übergänge zwischen Seiten und ein allgemeines App-ähnliches Gefühl für meine Website ermöglicht. Aber ich möchte auch das Plugin-Ökosystem frei nutzen können, das WordPress überhaupt erst so beliebt gemacht hat. Was ich will, ist etwas Headless-artiges. Fast Headless.

Ich konnte nichts finden, das dieser Beschreibung entsprach, also habe ich eines gebaut. Seitdem habe ich eine Handvoll Websites mit diesem Ansatz erstellt und die notwendigen JavaScript-Bibliotheken entwickelt, um es anderen zu erleichtern, ihre eigenen Fast Headless WordPress-Themes zu erstellen.

Vorstellung von Fast Headless WordPress

Fast Headless ist ein Ansatz für die Webentwicklung mit WordPress, der Ihnen viele der App-ähnlichen Vorteile eines Headless-Ansatzes sowie die einfache Entwicklung bietet, die mit einem traditionellen WordPress-Theme verbunden ist. Dies wird durch eine kleine JavaScript-App erreicht, die das Routing übernimmt und Ihre Website ähnlich wie eine Headless-App rendert, aber einen Fallback bietet, um dieselbe Seite stattdessen mit einer normalen WordPress-Anfrage zu laden. Sie können wählen, welche Seiten über die Fallback-Methode geladen werden, und können Logik entweder in das JavaScript oder das PHP einspeisen, um zu bestimmen, ob die Seite auf diese Weise geladen werden soll.

Sie können dies in Aktion auf der Demoseite sehen, die ich erstellt habe, um zu zeigen, was dieser Ansatz leisten kann.

Zum Beispiel verwendet eine der Websites, die diese Methode implementieren, ein Lernmanagementsystem namens LifterLMS, um WordPress-Kurse online zu verkaufen. Dieses Plugin verfügt über integrierte E-Commerce-Funktionen und richtet die Schnittstelle ein, die zum Hosten und Platzieren von Kursinhalten hinter einer Paywall erforderlich ist. Diese Website nutzt viele der integrierten Funktionen von LifterLMS – und ein großer Teil davon ist der Checkout-Warenkorb. Anstatt diese gesamte Seite neu zu erstellen, damit sie in meiner App funktioniert, habe ich sie einfach so eingestellt, dass sie über die Fallback-Methode geladen wird. Aus diesem Grund funktioniert diese Seite wie jedes alte WordPress-Theme und funktioniert folglich genau wie vorgesehen – alles, ohne dass ich etwas neu erstellen musste.

Pro

  1. Dies ist nach der Einrichtung einfach zu warten.
  2. Das Hosting ist so einfach wie bei einem typischen WordPress-Theme.
  3. Die Website fühlt sich genauso modern und schnell an wie eine Headless-Website.

Contra

  1. Sie müssen immer über zwei verschiedene Methoden nachdenken, um Ihre Website zu rendern.
  2. Es gibt nur begrenzte Auswahlmöglichkeiten für JavaScript-Bibliotheken, die mit dieser Methode effektiv sind.
  3. Diese App ist sehr eng mit WordPress verknüpft, sodass die Verwendung von Drittanbieter-REST-APIs schwieriger ist als bei Headless.

Wie es funktioniert

Damit etwas „Fast Headless“ ist, muss es mehrere Dinge können, darunter

  1. eine Seite mit einer WordPress-Anfrage laden,
  2. eine Seite mit JavaScript laden,
  3. Seiten identisch machen, unabhängig davon, wie sie gerendert werden,
  4. eine Möglichkeit bieten, zu wissen, wann eine Seite mit JavaScript oder PHP geladen werden soll, und
  5. 100%ige Parität bei allen gerouteten Seiten gewährleisten, unabhängig davon, ob sie mit JavaScript oder PHP gerendert werden.

Dies ermöglicht die Nutzung der progressiven Verbesserung. Da die Seite mit oder ohne JavaScript angezeigt werden kann, können Sie die Version verwenden, die am sinnvollsten ist, basierend auf der gestellten Anfrage. Ein vertrauenswürdiger Bot crawlt Ihre Website? Senden Sie ihm die Nicht-JavaScript-Version, um die Kompatibilität sicherzustellen. Eine Checkout-Seite funktioniert nicht wie erwartet? Erzwingen Sie das Laden ohne die App für den Moment und beheben Sie es vielleicht später.

Um all diese Punkte zu erreichen, habe ich eine Open-Source-Bibliothek namens Nicholas veröffentlicht, die ein fertiges Boilerplate enthält.

Trocken halten (DRY)

Die größte Sorge, die ich bei der Erstellung einer Fast Headless-App überwinden wollte, war die Aufrechterhaltung der Parität zwischen der Art und Weise, wie die Seite in PHP und JavaScript gerendert wird. Ich wollte mein Markup nicht an zwei verschiedenen Stellen erstellen und warten – ich wollte eine einzige Quelle für so viel Markup wie möglich. Dies schränkte sofort ein, welche JavaScript-Bibliotheken ich realistisch verwenden konnte (Entschuldigung, React!). Nach einiger Recherche und viel Experimentieren bin ich bei AlpineJS gelandet. Diese Bibliothek hat meinen Code einigermaßen DRY gehalten. Es gibt Teile, die für jeden zwingend neu geschrieben werden müssen (Schleifen zum Beispiel), aber die meisten signifikanten Markup-Teile können wiederverwendet werden.

Eine einzelne Beitrags-Vorlage, die mit PHP gerendert wird, könnte ungefähr so aussehen

<?php
if ( have_posts() ) {
  while ( have_posts() ) {
    the_post();
    if ( is_singular() ) {
      echo nicholas()->templates()->get_template( 'index', 'post', [
        'content' => Nicholas::get_buffer( 'the_content' ),
        'title'   => Nicholas::get_buffer( 'the_title' ),
      ] );
    }
  }
}
?>

Dieselbe Beitrags-Vorlage, die in JavaScript mit Alpine gerendert wird

<template x-for="(post, index) in $store.posts" :key="index">
  <?= nicholas()->templates()->get_template( 'index', 'post' ) ?>
</template>

Beide verwenden dieselbe PHP-Vorlage, sodass der gesamte Code innerhalb der eigentlichen Schleife DRY ist

$title   = $template->get_param( 'title', '' );

// Get the title that was passed into this template, fallback to empty string.
$content = $template->get_param( 'content', '' ); // Get the cotent passed into this template, fallback to empty string.

?>
<article x-data="theme.Post(index)">
  <!-- This will use the alpine directive to render the title, or if it's in compatibility mode PHP will fill in the title directly -->
  <h1 x-html="title"><?= $title ?></h1>
  <!-- This will use the Alpine directive to render the post content, or if it's in compatibility mode, PHP will fill in the content directly -->
  <div class="content" x-html="content"><?= $content ?></div>
</article>

Verwandt: Dieser Alpine.js-Ansatz ähnelt im Geiste dem Vue.js-Ansatz, der in „How to Build Vue Components in a WordPress Theme“ von Jonathan Land behandelt wird.

Erkennen, wann eine Seite im Kompatibilitätsmodus ausgeführt werden soll

Der „Kompatibilitätsmodus“ ermöglicht es Ihnen, jede Anfrage zu erzwingen, ohne das JavaScript zu laden, das die Headless-Version der Website ausführt. Wenn eine Seite für den Kompatibilitätsmodus eingerichtet ist, wird sie nur mit PHP geladen, und das App-Skript wird nie eingebunden. Dies ermöglicht es „Problemseiten“, die mit der App nicht wie erwartet funktionieren, ohne etwas neu schreiben zu müssen.

Es gibt verschiedene Möglichkeiten, eine Seite im Kompatibilitätsmodus auszuführen – einige erfordern Code, andere nicht. Nicholas fügt jedem Post-Typ einen Schalter hinzu, der es ermöglicht, einen Beitrag im Kompatibilitätsmodus zu erzwingen.

Zusätzlich können Sie manuell jede URL hinzufügen, um sie im Kompatibilitätsmodus über die Nicholas-Einstellungen zu laden.

Dies ist ein guter Anfang, aber ich habe festgestellt, dass ich normalerweise automatisch erkennen kann, wann eine Seite im Kompatibilitätsmodus geladen werden muss, basierend auf den Blöcken, die in einem Beitrag gespeichert sind. Nehmen wir zum Beispiel an, Sie haben Ninja Forms auf Ihrer Website installiert und möchten die von ihnen bereitgestellte Validierungs-JavaScript-Funktion verwenden, anstatt Ihre eigene neu zu erstellen. In diesem Fall müssten Sie den Kompatibilitätsmodus für jede Seite erzwingen, auf der ein Ninja-Formular vorhanden ist. Sie könnten manuell jede URL einzeln hinzufügen, oder Sie können eine Abfrage verwenden, um den gesamten Inhalt abzurufen, der einen Ninja Forms-Block auf der Seite hat. Etwas wie das hier

add_filter( 'nicholas/compatibility_mode_urls', function ( $urls ) {
  // Filter Ninja Forms Blocks
  $filtered_urls = Nicholas::get_urls_for_query( [
    'post_type' => 'any',
    's' => 'wp:ninja-forms/form', // Find Ninja Forms Blocks
  ] );

  return array_merge( $urls, $filtered_urls );
} );

Das fügt automatisch jede Seite mit einem Ninja Forms-Block zur Liste der URLs hinzu, die im Kompatibilitätsmodus geladen werden. Dies verwendet nur `WP_Query`-Argumente, sodass Sie hier beliebige Werte übergeben können, um zu bestimmen, welcher Inhalt zur Liste hinzugefügt werden soll.

Erweiterung der App

Unter der Haube verwendet Nicholas einen leichten Router, der mithilfe eines Middleware-Musters erweitert werden kann, ähnlich wie eine Express-App Middleware handhabt. Wenn eine angeklickte Seite geroutet wird, durchläuft das System jedes Middleware-Element und routet schließlich die Seite. Standardmäßig tut der Router nichts; er kommt jedoch mit mehreren vorgefertigten Middleware-Teilen, die es Ihnen ermöglichen, den Router nach Belieben zusammenzustellen.

Ein einfaches Beispiel würde ungefähr so aussehen

// Import WordPress-specific middleware
import {
  updateAdminBar,
  validateAdminPage,
  validateCompatibilityMode
} from 'nicholas-wp/middlewares'

// Import generic middleware
import {
  addRouteActions,
  handleClickMiddleware,
  setupRouter,
  validateMiddleware
} from "nicholas-router";

// Do these actions, in this order, when a page is routed.
addRouteActions(
  // First, validate the URL
  validateMiddleware,
  // Validate this page is not an admin page
  validateAdminPage,
  // Validate this page doesn't require compatibility mode
  validateCompatibilityMode,
  // Then, we Update the Alpine store
  updateStore,
  // Maybe fetch comments, if enabled
  fetchComments,
  // Update the history
  updateHistory,
  // Maybe update the admin bar
  updateAdminBar
)

// Set up the router. This also uses a middleware pattern.
setupRouter(
  // Setup event listener for clicks
  handleClickMiddleware
)

Von hier aus könnten Sie erweitern, was passiert, wenn eine Seite geroutet wird. Vielleicht möchten Sie die Seite nach Code zum Hervorheben scannen oder vielleicht den Inhalt des <head>-Tags ändern, um ihn an die neu geroutete Seite anzupassen. Vielleicht sogar eine Caching-Schicht einführen. Unabhängig davon, was Sie tun müssen, ist das Hinzufügen der erforderlichen Aktionen so einfach wie die Verwendung von addRouteAction oder setupRouter.

Nächste Schritte

Dies war ein kurzer Überblick über einige der Schlüsselkomponenten, die ich zur Implementierung des Fast Headless-Ansatzes verwendet habe. Wenn Sie tiefer eintauchen möchten, empfehle ich Ihnen meinen Kurs bei WP Dev Academy. Dieser Kurs ist eine Schritt-für-Schritt-Anleitung zum Erstellen einer Fast Headless WordPress-Website mit modernen Werkzeugen. Ich empfehle Ihnen auch, mein Fast Headless Boilerplate auszuprobieren, das Ihnen beim Start Ihres eigenen Projekts helfen kann.