Gutenberg ist der Standard-Editor für WordPress. Mit dem Editor kannst du Inhalte mit einzelnen Blöcken für Text, Bilder, Videos und andere Seitenelemente per Drag-and-Drop erstellen und gestalten. Dieser Ansatz verbessert die Flexibilität und die Gestaltungsmöglichkeiten von WordPress.
In diesem Leitfaden wird erklärt, wie du Gutenberg-Inhalte über die WordPress REST API in einer statischen Next.js-Website als HTML parsen kannst.
Voraussetzungen
Um dieser Anleitung zu folgen, brauchst du:
- Node.js und npm (Node Package Manager) oder yarn auf deinem Computer installiert
- Grundkenntnisse in JavaScript und React
- Eine WordPress-Website mit ein paar veröffentlichten Beiträgen
Abrufen von Gutenberg-Inhalten über eine REST-API
Um programmatisch mit deiner WordPress-Website zu interagieren und in Gutenberg-Blöcken strukturierte Inhalte abzurufen, verwendest du die WordPress REST API oder das WPGraphQL-Plugin. Mit diesen Tools kannst du deine WordPress-Inhalte im JSON-Format abrufen.
Um den Zugriff auf JSON-Daten über die REST-API zu ermöglichen, musst du die Permalink-Einstellungen in WordPress anpassen (nicht auf „Plain“). Dies ermöglicht den API-Zugriff über eine strukturierte URL, wie folgt:
https://yoursite.com/wp-json/wp/v2
Indem du API-Anfragen an diese URL stellst, kannst du programmatisch verschiedene Informationen abrufen und Vorgänge auf deiner WordPress-Website durchführen. Du kannst zum Beispiel eine Liste von Beiträgen abrufen, indem du eine GET-Anfrage hierhin sendest:
https://yoursite.com/wp-json/wp/v2/posts
Du erhältst ein JSON-Objekt mit Informationen über die Beiträge auf deiner WordPress-Website, einschließlich Titel, Inhalt, Autorendetails und mehr.
Gutenberg-Blöcke als HTML parsen
Wenn du Beiträge von einer WordPress-Website abrufst, die den Gutenberg-Editor verwendet, können die gespeicherten Inhalte in der Datenbank eine Mischung aus HTML- und JSON-Metadaten enthalten, um verschiedene Blocktypen wie Zitate und Galerien zu beschreiben. Zum Beispiel:
<!-- wp:quote {"className":"inspirational-quote","style":{"typography":{"fontSize":"large"}}} -->
<blockquote class="wp-block-quote inspirational-quote has-large-font-size"><p>“The journey of a thousand miles begins with one step.”</p><cite>Lao Tzu</cite></blockquote>
<!-- /wp:quote -->
<!-- wp:gallery {"ids":[34,35],"columns":2,"linkTo":"none","sizeSlug":"medium","className":"custom-gallery"} -->
<ul class="wp-block-gallery columns-2 is-cropped custom-gallery"><li class="blocks-gallery-item"><figure><img src="http://example.com/wp-content/uploads/2021/09/image1-300x200.jpg" alt="A breathtaking view of the mountains" class="wp-image-34"/></figure></li><li class="blocks-gallery-item"><figure><img src="http://example.com/wp-content/uploads/2021/09/image2-300x200.jpg" alt="Serene lakeside at dawn" class="wp-image-35"/></figure></li></ul>
<!-- /wp:gallery -->
Dieses Snippet zeigt zwei Gutenberg-Blöcke: ein Zitat und eine Galerie. Jeder ist mit JSON-Metadaten versehen, die in HTML-Kommentaren gekapselt sind. Die Metadaten definieren Attribute wie Klassennamen, Stile und andere Konfigurationen, die für die Darstellung des Blocks relevant sind.
Wenn du diese Blöcke über die WordPress REST API oder WPGraphQL abrufst, verarbeitet WordPress sie und wandelt die Kombination aus HTML- und JSON-Metadaten in vollständig gerenderte HTML-Elemente um, die du direkt in Webseiten einbinden kannst. Das umgewandelte HTML für die oben genannten Blöcke würde wie folgt aussehen:
<blockquote class="wp-block-quote inspirational-quote has-large-font-size"><p>“The journey of a thousand miles begins with one step.”</p><cite>Lao Tzu</cite></blockquote>
<ul class="wp-block-gallery columns-2 is-cropped custom-gallery">
<li class="blocks-gallery-item"><figure><img loading="lazy" src="http://example.com/wp-content/uploads/2021/09/image1-300x200.jpg" alt="A breathtaking view of the mountains" class="wp-image-34" sizes="(max-width: 300px) 100vw, 300px" /></figure></li>
<li class="blocks-gallery-item"><figure><img loading="lazy" src="http://example.com/wp-content/uploads/2021/09/image2-300x200.jpg" alt="Serene lakeside at dawn" class="wp-image-35" sizes="(max-width: 300px) 100vw, 300px" /></figure></li>
</ul>
Für Entwickler, die entkoppelte oder Headless-Anwendungen mit JavaScript-Frameworks wie Next.js erstellen, ist dies eine einfache Methode, um Inhalte anzuzeigen, indem sie das HTML direkt in die Seite einfügen und die dangerouslySetInnerHTML
Eigenschaft zum Rendern des Markups verwenden.
<div dangerouslySetInnerHTML={{ __html: <raw_html_string> }} />
Zusätzlich musst du eventuell weitere Formatierungen für Elemente wie Links vornehmen und überflüssige Zeilenumbrüche behandeln (\n
), was in diesem Leitfaden später erklärt wird.
Inhalt der Gutenberg-Blöcke in die statische Next.js-Site einbinden
In diesem Abschnitt werden wir WordPress-Inhalte in ein Next.js-Projekt holen und die Gutenberg-Blöcke als HTML parsen.
- Beginne damit, eine Funktion einzurichten, die Beiträge von deiner WordPress-Website abruft. Öffne die Datei src/page.js in deinem Projekt und ersetze ihren Inhalt durch den folgenden Codeschnipsel:
const getWpPosts = async () => { const res = await fetch('https://yoursite.com/wp-json/wp/v2/posts'); const posts = await res.json(); return posts; };
Diese asynchrone Funktion führt eine API-Anfrage an die WordPress REST API durch. Sie holt alle auf deiner Seite verfügbaren Beiträge ab und gibt sie als Array zurück.
- Als Nächstes verwenden wir die abgerufenen Beiträge in einer einfachen Next.js-Seitenkomponente, indem wir die Beiträge auf der Konsole protokollieren und eine einfache Begrüßung darstellen:
const page = async () => { const posts = await getWpPosts(); console.log(posts); return ( <div> <h1>Hello World</h1> </div> ); }; export default page;
Wenn du dein Projekt mit
npm run dev
ausführst, zeigt es die Nachricht „Hello World“ an und protokolliert die abgerufenen Beiträge im Terminal.[ { "_links" : { "about" : [...], "author" : [...], "collection" : [...], "curies" : [...], "predecessor-version" : [...], "replies" : [...], "self" : [...], "version-history" : [...], "wp:attachment" : [...], "wp:term" : [...] }, "author" : 1, "categories" : [...], "comment_status" : "open", "content" : { "protected" : false, "rendered" : "\n<p>Fire, a primal force, captivates with its <strong>flickering flames</strong>, evoking both awe and caution. Its <quote>dance</quote> symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate.</p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"148\" src=\"https://img.example.com/wp-content/uploads/2024/02/burningbuilding.jpg\" alt=\"\" class=\"wp-image-14\"/></figure>\n\n\n\n<p>In ancient times, fire was a beacon of light and warmth, essential for survival. Today, it remains a symbol of human ingenuity and danger. From the comforting glow of a hearth to the destructive fury of wildfires, fire’s dual nature reminds us of our fragile relationship with the elements.</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https://img.example.com/premium-photo/painting-burning-building-illuminated-by-bright-flames-night_168058-249.jpg?w=1380\" alt=\"\"/></figure>\n\n\n\n<p>You can check out other articles on our blog:</p>\n\n\n\n<ul>\n<li><a href=\"https://yoursite.com/?p=6\">Lorem Ipsum: Beginnings</a></li>\n\n\n\n<li><a href=\"https://yoursite.com/?p=9\">Lorem Ipsum: Act 2</a></li>\n\n\n\n<li><a href=\"https://yoursite.com/?p=11\">Lorem Ipsum: Act 3</a></li>\n</ul>\n" }, "date" : "2024-02-27T12:08:30", "date_gmt" : "2024-02-27T12:08:30", "excerpt" : { "protected" : false, "rendered" : "<p>Fire, a primal force, captivates with its flickering flames, evoking both awe and caution. Its dance symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate. In ancient times, fire was a beacon of light and warmth, […]</p>\n" }, "featured_media" : 0, "format" : "standard", "guid" : { "rendered" : "https://yoursite.com/?p=13" }, "id" : 13, "link" : "https://yoursite.com/?p=13", "meta" : { "footnotes" : "" }, "modified" : "2024-02-29T16:45:36", "modified_gmt" : "2024-02-29T16:45:36", "ping_status" : "open", "slug" : "fire-fire", "status" : "publish", "sticky" : false, "tags" : [], "template" : "", "title" : { "rendered" : "Fire" }, "type" : "post" }, }, ... ]
Die JSON-Objekte, die die einzelnen Gutenberg-Beitragsdaten repräsentieren, enthalten verschiedene Felder, darunter die Felder content und excerpt, die als Gutenberg-Blöcke zurückgegeben und als HTML-Strings geparst werden.
- Um diese HTML-Inhalte in Next.js korrekt darzustellen, verwenden wir die Eigenschaft
dangerouslySetInnerHTML
:const page = async () => { const posts = await getWpPosts(); return ( <> <h1> Headless Blog </h1> <div> {posts.map((post) => ( <Link href={'/blog/' + post.id} key={post.id}> <h2> {post.title.rendered} <span>-></span> </h2> <div dangerouslySetInnerHTML={{ __html: post.excerpt.rendered }} /> </Link> ))} </div> </> ); }; export default page;
In dieser aktualisierten Komponente mappen wir das Array der abgerufenen Beiträge, um eine Liste von Beitragsauszügen zu erstellen. Jeder Auszug wird für die Navigation in eine
Link
Komponente verpackt, die den Titel des Beitrags und einen Ausschnitt des Inhalts anzeigt.Die Eigenschaft
dangerouslySetInnerHTML
wird verwendet, um den HTML-Inhalt des Feldesexcerpt.rendered
zu parsen und zu rendern. - Als nächstes erstellst du eine Datei blog/[id]/page.js im Anwendungs-Verzeichnis. Du verwendest Ordner, um Routen zu definieren. Indem du also einen Blog-Ordner erstellst, definierst du die Blog-Route. Du kombinierst dies mit dynamischem Routing, um Routen für jeden Beitrag zu erstellen.
- Jeder Beitrag hat eine ID. Mit dieser ID erstellst du eine eindeutige Route,
/blog/{post_id}
, in deiner Anwendung. Füge den folgenden Code ein:import Link from 'next/link'; export async function generateStaticParams() { const res = await fetch('https://yoursite.com/wp-json/wp/v2/posts'); const posts = await res.json(); return posts.map((post) => { return { params: { id: post.id.toString(), }, }; }); } export async function getPost(id) { const response = await fetch('https://yoursite.com/wp-json/wp/v2/posts/' + id); const post = await response.json(); return post; }
Die Funktion
generateStaticParams()
generiert statisch Routen zur Erstellungszeit auf der Grundlage der entsprechenden ID, die für jeden Beitrag zurückgegeben wird. Die FunktiongetPost()
holt Gutenberg-Daten von der REST-API für den Beitrag mit einer übergebenen ID.Ein früherer Abschnitt zeigte ein Beispiel für geparste Gutenberg-Daten, die von der REST-API für einen Beitrag zurückgegeben wurden. Im Moment interessieren wir uns nur für das Feld
content.rendered
:[ { ... "content": { "rendered" : "\n<p>Fire, a primal force, captivates with its <strong>flickering flames</strong>, evoking both awe and caution. Its <quote>dance</quote> symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate.</p>\n\n\n\n<figure> class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"148\" src=\"https://img.example.com/wp-content/uploads/2024/02/burningbuilding.jpg\" alt=\"\" class=\"wp-image-14\"/></figure>\n\n\n\n<p>In ancient times, fire was a beacon of light and warmth, essential for survival. Today, it remains a symbol of human ingenuity and danger. From the comforting glow of a hearth to the destructive fury of wildfires, fire’s dual nature reminds us of our fragile relationship with the elements.</p>\n\n\n\n<figure> class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https://img.example.com/premium-photo/painting-burning-building-illuminated-by-bright-flames-night_168058-249.jpg?w=1380\" alt=\"\"/></figure>\n\n\n\n<p>You can check out other articles on our blog:</p>\n\n\n\n<ul>\n<li><a> href=\"https://yoursite.com/?p=6\">Lorem Ipsum: Beginnings</a></li>\n\n\n\n<li><a> href=\"https://yoursite.com/?p=9\">Lorem Ipsum: Act 2</a></li>\n\n\n\n<li><a> href=\"https://yoursite.com/?p=11\">Lorem Ipsum: Act 3</a></li>\n</ul>\n" }, ... } ]
Dieses Feld enthält das Roh-HTML des Beitrags. Es kann direkt mit der Eigenschaft
dangerouslySetInnerHTML
wie folgt gerendert werden:<div dangerouslySetInnerHTML={{ __html: <raw_html_string> }} />
. - Als Nächstes kannst du die Daten verarbeiten, indem du interne Links analysierst und die Größe von Bildern änderst. Installiere das Paket
html-react-parser
, um das Parsen von Tags zu vereinfachen:npm install html-react-parser --save
- Füge den folgenden Code in die Datei blog/[id]/page.js ein:
import parse, { domToReact } from "html-react-parser"; /* * We use a regular expression (pattern) to match the specific URL you want to replace. * The (\d+) part captures the numeric ID after ?p=. * Then, we use the replacement string 'data-internal-link="true" href="/blog/$1"', * where $1 is a placeholder for the captured ID. */ export function fixInternalLinks(html_string) { const pattern = /href="https:\/\/yoursite.com\/\?p=(\d+)"/g; const replacement = 'data-internal-link="true" href="/blog/$1"'; return html_string.replace(pattern, replacement); } export function parseHtml(html) { // Replace 2+ sequences of '\n' with a single '<br />' tag const _content = html.replace(/\n{2,}/g, '<br />'); const content = fixInternalLinks(_content); const options = { replace: ({ name, attribs, children }) => { // Convert internal links to Next.js Link components. const isInternalLink = name === "a" && attribs["data-internal-link"] === "true"; if (isInternalLink) { return ( <Link href={attribs.href} {...attribs}> {domToReact(children, options)} </Link> ); } else if (name === "img") { attribs["width"] = "250"; attribs["height"] = "150"; return ( <img {...attribs}/> ); } }, }; return parse(content, options); }
Die Funktion
fixInternalLinks()
verwendet einen regulären Ausdruck, um im HTML-String Links zu Beiträgen auf deiner WordPress-Seite zu finden. Im rohen HTML kannst du sehen, dass der Beitrag einList
Tag mit Links zu anderen Beiträgen auf deiner Seite enthält. Diese Links werden durch interne Links zu Routen auf deiner statischen Seite ersetzt.Die Funktion
parseHTML()
findet mehrere Sequenzen von überflüssigen Zeilenumbrüchen,n
und ersetzt sie durch<br />
Tags. Sie findet auch interne Links und wandelt die Anker-Tags in Link-Tags um. Anschließend passt diese Funktion die Größe von Bildern mithilfe von Tag-Attributen an. - Um die Haupt-UI für jede dynamische Route zu erstellen, füge den folgenden Code ein:
export default async function Post({ params }) { const post = await getPost(params.id); const content = parseHtml(post.content.rendered); return ( <> <h1> {post.title.rendered} </h1> <div>{content}</div> </> ); }
Nach dem Parsen des Roh-HTML aus den Gutenberg-Daten gibt der Code JSX zurück, das die formatierte Benutzeroberfläche der Seite darstellt.
Wenn du dein Projekt ausführst, wird auf der Startseite eine Liste der Beiträge in deinem WordPress angezeigt. Wenn du auf einzelne Beiträge klickst, werden die geparsten Gutenberg-Inhalte richtig dargestellt.
Bereitstellen deiner statischen Next.js-Website auf Kinsta
Wenn du Headless WordPress mit modernen Frameworks wie Next.js kombinierst, ist es wichtig, eine kosteneffiziente Lösung für die Bereitstellung zu finden, vor allem wenn du ein leistungsstarkes WordPress-Hosting wie das von Kinsta für deine WordPress-Website nutzt. Der Statische-Seiten-Hosting Dienst von Kinsta bietet eine nahtlose und kostengünstige Möglichkeit, deine Website online zu stellen.
Kinsta ermöglicht es dir, bis zu 100 statische Websites kostenlos zu hosten. Als erstes musst du deinen Code zu einem bevorzugten Git-Anbieter (Bitbucket, GitHub oder GitLab) pushen. Sobald dein Repo fertig ist, befolge diese Schritte, um deine statische Website bei Kinsta einzurichten:
- Logge dich ein oder erstelle ein Konto, um dein MyKinsta-Dashboard zu sehen.
- Autorisiere Kinsta bei deinem Git-Anbieter.
- Klicke in der linken Seitenleiste auf Statische Seiten und dann auf Website hinzufügen.
- Wähle das Repository und den Branch aus, von dem aus du bereitstellen möchtest.
- Gib deiner Site einen eindeutigen Namen.
- Füge die Build-Einstellungen in folgendem Format hinzu:
- Build-Befehl:
npm run build
- Node-Version:
18.16.0
- Verzeichnis veröffentlichen:
out
- Build-Befehl:
- Zum Schluss klickst du auf Website erstellen.
Und das war’s! Innerhalb weniger Sekunden hast du eine fertige Website. Du erhältst einen Link, über den du auf die bereitgestellte Version deiner Website zugreifen kannst. Du kannst später deine eigene Domain und dein SSL-Zertifikat hinzufügen, wenn du möchtest.
Als Alternative zum statischen Website-Hosting kannst du deine statische Website auch mit dem Anwendungs-Hosting Dienst von Kinsta bereitstellen. Dieser bietet eine größere Hosting-Flexibilität, ein breiteres Spektrum an Vorteilen und Zugang zu robusteren Funktionen wie Skalierbarkeit, individuelle Bereitstellung mit einem Dockerfile und umfassende Analysen mit Echtzeit- und historischen Daten. Außerdem musst du dein Next.js-Projekt nicht für statisches Rendering konfigurieren.
Zusammenfassung
In diesem Leitfaden wurde erklärt, wie du Gutenberg-Blockinhalte über die WordPress-API effektiv als HTML integrieren und parsen kannst. Das macht es möglich, jede Art von Inhalt auf deinem Frontend zu rendern, wenn du Headless WordPress verwendest.
Du kannst dein Headless WordPress auf unserem Managed WordPress Hosting Service hosten und deine statische Website auf unserem Statische-Seiten-Hosting Dienst bereitstellen. Das bedeutet, dass du alles über deine Website in einem einzigen Dashboard findest: MyKinsta.
Wenn du dich für Kinsta entscheidest, profitierst du von einem Hosting-Anbieter, der die optimale Leistung und Skalierbarkeit deiner Website in den Vordergrund stellt und sie gleichzeitig mit fortschrittlichen Sicherheitsmaßnahmen schützt. Teste Kinsta noch heute!
Was hältst du von Headless WordPress und seiner Darstellung? Hast du eine bessere Möglichkeit, Gutenberg-Blöcke zu integrieren? Teile deine Ideen im Kommentarbereich mit!
Schreibe einen Kommentar