Definieren von Redirects für Next.js-Applications
Bei der Neugestaltung einer Website kann es erforderlich sein, den URL-Pfad einer Seite zu ändern.
Sie können zum Beispiel die Kontaktseite in den Abschnitt "Über uns" verlegen. Diese Änderung sollte dazu führen, dass die Seite, die derzeit über den Pfad /contact aufgerufen wird, über den neuen Pfad /about-us/contact aufgerufen wird.
Bei einer solchen Änderung müssen die Webteams bedenken, dass der ursprüngliche Link möglicherweise immer noch verwendet wird, z. B. in sozialen Medien oder auf anderen Websites. Um zu vermeiden, dass Datenverkehr von diesen Quellen verloren geht - und Frustration bei den Nutzern entsteht - verwenden wir Weiterleitungen.
Bei der Bereitstellung von Inhalten nach dem Headless-Konzept kann die Verwaltung von Weiterleitungen in großem Umfang eine Herausforderung darstellen.
In diesem Blogpost wird gezeigt, wie man eine Magnolia Content App erstellt, die es Autoren ermöglicht, Redirects für eine Headless-Umgebung einfach zu verwalten und wie man die definierten Redirects an eine Next.js-Application über REST- und GraphQL-Methoden übergibt.
Anforderungen
Magnolia 6.2.25 oder höher
Webooks-Modul 1.0.0 oder höher
REST Client Modul 2.0.4 oder höher
GraphQL-Modul 1.1.2 oder höher
Next.js Application
Der einfachste Weg, um mit Magnolia und Next.js zu beginnen, ist das minimal-headless-spa-demos-Tutorial. Sie können auch unser nextjs-redirect-demo-Projekt erkunden, in dem die Next.js-Application und die Redirects Content App bereits eingerichtet sind.
Erstellen der Umleitungsanwendung
Für dieses Tutorial gehen wir davon aus, dass Magnolia und Next.js eingerichtet sind und laufen.
Zunächst müssen wir festlegen, wie Weiterleitungen erstellt und gespeichert werden, damit die Autoren von Inhalten sie verwalten können.
Beginnen wir mit der Erstellung eines neuen Verzeichnisses für das Magnolia Light Modul namens nextjs-redirect-lm. Innerhalb dieses Verzeichnisses werden wir in Kürze einen Content Type und eine Content App für die Weiterleitungen erstellen.
Erstellen des Inhaltstyps für die Weiterleitung
Magnolia Content Types definieren und beschreiben die Typen und die Struktur von Inhalten in Ihrem Projekt. Definieren wir einen neuen Content Type namens redirect mit drei Eigenschaften:
name: Dient als eindeutiger Bezeichner für jede Weiterleitung.
rootPage: Diese Eigenschaft steht für die aktuelle Stammseite
- die für die Umleitung vorgesehen ist. Mit anderen Worten
- es handelt sich um die Ausgangsseite
- von der aus die Benutzer umgeleitet werden.
redirect: Diese Eigenschaft steht für die Umleitungsregeln. Sie setzt sich aus mehreren Attributen zusammen: 1)from: Dieses Feld stellt den ursprünglichen URL-Pfad dar
- von dem die Umleitung ausgeht. 2)to: Dieses Feld steht für die Ziel-URL. Dabei kann es sich entweder um einen internen Link innerhalb Ihrer Website oder um einen externen Link zu einer anderen Website handeln. 3) Code: Dieses Feld gibt den HTTP-Statuscode an
- der mit der Umleitung gesendet wird.
Erstellen Sie die Datei /nextjs-redirect-lm/contentTypes/redirect.yaml für das obige Inhaltsmodell:
datasource: workspace: redirects autoCreate: true model: nodeType: lib:redirect properties: - name: name - name: rootPage - name: redirect type: redirectItem multiple: true subModels: - name: redirectItem properties: - name: from - name: to type: toItem - name: code - name: toItem properties: - name: field - name: internal - name: custom
Nachdem wir den Inhaltstyp erstellt haben, können wir nun eine Inhalts-App erstellen.
Erstellen der Redirects Content App
Eine Magnolia Content App ist eine App zur Verwaltung strukturierter Inhalte. Sie definiert das Layout der Eigenschaften des Inhaltstyps und andere Eigenschaften. Definieren wir eine neue Content App namens redirects-app.
Erstellen Sie die Datei /nextjs-redirect-lm/apps/redirects-app.yaml:
!content-type:redirect name: redirects-app label: Redirects App subApps: browser: actions: activate: availability: multiple: true detail: form: properties: name: $type: textField required: true rootPage: $type: pageLinkField showOptions: true textInputAllowed: true converterClass: info.magnolia.ui.editor.converter.JcrNodeToPathConverter erforderlich: true redirect: $type: jcrMultiField field: $type: compositeField properties: from: $type: textField erforderlich: true to: $type: switchableField field: $type: comboBoxField erforderlich: true datasource: $type: optionListDatasource options:
- name: internal value: internal - name: custom value: custom itemProvider: $type: jcrChildNodeProvider forms: - name: internal properties: internal: $type: pageLinkField showOptions: true textInputAllowed: true converterClass: info.magnolia.ui.editor.converter.JcrNodeToPathConverter erforderlich: true - name: custom Eigenschaften: custom: $type: textField erforderlich: true code: $type: textField erforderlich: true
Wir haben nun das Gesamtlayout unserer Inhalts-App definiert.
Beachten Sie, dass die Eigenschaft rootPage einen pageLinkField-Typ hat und dass eine redirect-Eigenschaft aus einem from-, to- und code-Feld besteht.
Beachten Sie auch, dass die Eigenschaft to vom Typ switchableField mit zwei möglichen Optionen ist:
intern
benutzerdefiniert
Sie können erwägen, die Inhalts-App um eine Beschreibung und Feldvalidatoren zu erweitern, die sicherstellen, dass die Felder im richtigen Format und in der richtigen Länge eingegeben werden.
Zu diesem Zeitpunkt sollte die neue App in Magnolia sichtbar sein:
Hinzufügen von Weiterleitungen
Öffnen Sie nun die Redirects App und klicken Sie auf die Schaltfläche "Element hinzufügen". Sie sollten das folgende Formular sehen:
Machen Sie weiter und erstellen Sie Ihre erste Umleitung mit den Parametern aus dem Screenshot.
Abrufen von Daten
Wie können wir nun auf die Daten zugreifen, die wir gerade in der Inhalts-App eingegeben haben?
Es gibt zwei Möglichkeiten, die Daten aus einer Inhalts-App zu holen: über einen REST-Bereitstellungsendpunkt oder eine GraphQL-API.
Abrufen von Daten vom REST-Lieferendpunkt
Kehren Sie zum Ordner "Light Module" zurück und erstellen Sie eine neue Datei, um den REST-Bereitstellungsendpunkt zu erstellen.
/nextjs-redirect-lm/restEndpoints/delivery/redirects_v1.yaml:
class: info.magnolia.rest.delivery.jcr.v2.JcrDeliveryEndpointDefinition workspace: redirects depth: 3 includeSystemProperties: false bypassWorkspaceAcls: true limit: 50 systemProperties: - mgnl:lastModified - mgnl:created
Der Endpunkt ist sofort nach der Erstellung seiner Konfiguration verfügbar und wir können auf die Daten unter dieser URL zugreifen: http://localhost:8080/magnoliaAuthor/.rest/delivery/redirects/v1/?rootPage%5Blike%5D=%2Fnextjs-redirect-demo%25
Beachten Sie das ?rootPage[like]=/nextjs-redirect-demo% in der URL? Mit diesem Teil können wir die Ergebnisse anhand von Anfrageparametern filtern.
Wenn Sie im vorherigen Schritt eine Weiterleitung definiert haben, sollte die Antwort wie folgt aussehen:
JSON:
{ "total": 1, "offset": 0, "limit": 50, "results": [ { "@name": "Contact-Page-Redirect", "@path": "/Kontakt-Seiten-Weiterleitung", "@id": "4c7c577e-71b8-47a6-8fe2-c94fc496f11d", "@nodeType": "mgnl:content", "rootPage": "/nextjs-redirect-demo", "name": "Contact Page Redirect", "mgnl:lastModified": "2022-10-31T14:04:11.398+01:00", "mgnl:created": "2022-10-31T14:04:11.397+01:00", "redirect": { "@name": "redirect", "@path": "/Kontakt-Seite-Redirect/redirect", "@id": "a36b3c4a-904a-4540-841c-da953baf52b6", "@nodeType": "mgnl:contentNode", "mgnl:lastModified": "2022-10-31T14:04:11.413+01:00", "mgnl:created": "2022-10-31T14:04:11.413+01:00", "redirect0": { "@name": "redirect0", "@path": "/Contact-Page-Redirect/redirect/redirect0", "@id": "1c59c77f-c6c6-4c4f-8346-22056a1ecf93", "@nodeType": "mgnl:contentNode", "from": "/contacts", "code": "301", "mgnl:lastModified": "2022-10-31T14:04:11.437+01:00", "mgnl:created": "2022-10-31T14:04:11.437+01:00", "to": { "@name": "to", "@path": "/Kontakt-Seite-Redirect/redirect/redirect0/to", "@id": "c5789397-05ba-45b3-b7ff-1d810760c3e1", "@nodeType": "mgnl:contentNode", "internal": "/nextjs-redirect-demo/about-us/contacts", "mgnl:lastModified": "2022-10-31T14:04:11.439+01:00", "field": "internal", "mgnl:created": "2022-10-31T14:04:11.439+01:00", "@nodes": [] }, "@nodes": ["to"] }, "@nodes": ["redirect0"] }, "@nodes": ["redirect"] } ] }
Abruf von Daten aus der GraphQL API
Zuvor haben wir einen Inhaltstyp mit unserem Inhaltsmodell definiert. Mit der GraphQL-API unter http://localhost:8080/magnoliaAuthor/.graphql können Sie bestimmte Daten abfragen, indem Sie eine POST-Anfrage mit der Abfrage im Textkörper senden, in der Sie die abzurufenden Inhaltseigenschaften angeben.
Zum Beispiel können Sie alle Weiterleitungen abfragen, bei denen die Eigenschaft rootPage mit einer bestimmten Zeichenfolge beginnt:
JSON
{ redirects (filter: "@rootPage LIKE '/nextjs-redirect-demo%'"){ redirect { from to { field internal custom } code } } }
Die GraphQL-API antwortet mit einem JSON-Objekt, das die Struktur Ihrer Abfrage widerspiegelt und mit den angeforderten Daten gefüllt ist. Sie können diese Daten dann direkt in Ihrer Application verwenden.
Aufruf an alle Frontend-Entwickler
Verwenden Sie den Headless-Ansatz für Magnolia. Sehen Sie sich unsere gesamte Headless-Dokumentation an.
Parsing der Daten
Um die Redirect-Daten in Next.js zu verwenden, müssen wir sie analysieren.
Parsing von Daten aus der REST Delivery API
Da wir bei REST nicht wählen können, welche Eigenschaften wir abrufen wollen, müssen wir dies manuell tun.
const nodeName = "/nextjs-redirect-demo" const REST_API = "http://localhost:8080/magnoliaAuthor/.rest/delivery/redirects/v1" async function parseRedirectsREST() { const redirects = await fetchAPI(`${REST_API}/?rootPage%5Blike%5D=${nodeName}%25`); return redirects.results.flatMap(parseRedirectItem); } function parseRedirectItem(item) { const rootPage = item.rootPage.replace(nodeName, ""); return item.redirect["@nodes"].map((redirectNode) => ({ from: rootPage + item.redirect[redirectNode].from, to: parseRedirectTo(item.redirect[redirectNode].to), code: item.redirect[redirectNode].code, })); } function parseRedirectTo(to) { return { field: to.field, custom: to.custom, internal: replaceNodeName(to.internal), }; } function replaceNodeName(url) { return url?.replace(nodeName, "/")?.replace("//", "/"); } async function fetchAPI(url, options) { try { const response = await fetch(url, options); if (!response.ok) { throw new Error(`Ein Fehler ist aufgetreten: ${response.status}`); } return await response.json(); } catch (error) { console.error(error); return []; } }
Parsen von Daten aus der GraphQL API
Mit GraphQL können wir die Eigenschaften angeben, die wir abrufen wollen, was den Parsing-Prozess erleichtert.
const nodeName = "/nextjs-redirect-demo" const GraphQL_API = "http://localhost:8080/magnoliaAuthor/.graphql" async function parseRedirectsGRAPHQL() { const options = { method: "POST", headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: JSON.stringify({ query: ` { redirects (filter: "@rootPage LIKE '/nextjs-redirect-demo%'"){ redirect { from to { field internal custom } code } } } } }) }; const response = await fetchAPI(GraphQL_API, options); let parsedRed = response?.data?.redirects[0]?.redirect || []; return parsedRed.map(item => { item.to.internal = replaceNodeName(item.to.internal); return item; }); } function replaceNodeName(url) { return url?.replace(nodeName, "/")?.replace("//", "/"); } async function fetchAPI(url, options) { try { const response = await fetch(url, options); if (!response.ok) { throw new Error(`Ein Fehler ist aufgetreten: ${response.status}`); } return await response.json(); } catch (error) { console.error(error); return []; } }
Ergebnis des Parsing
Basierend auf den zuvor eingegebenen Daten erzeugen die beiden Funktionen parseRedirectsREST und parseRedirectsGRAPHQL das folgende Array:
JSON
[ { "von": "/contacts", "to": { "field": "intern", "intern": "/about-us/contacts", "custom": null }, "code": "301" } ]
Überprüfung auf Weiterleitungen mit Next.js Middleware
Next.js Middleware hat eine großartige Funktion, mit der wir Code ausführen können, bevor eine Anfrage abgeschlossen ist. Wir können sie nutzen, um auf Weiterleitungen zu prüfen.
Erstellen Sie dazu eine Datei middleware.js im Stammverzeichnis Ihrer Next.js-Application.
Das folgende Beispiel funktioniert sowohl mit REST- als auch mit GraphQL-Antworten. Bitte kommentieren Sie die Abrufoption aus, die Sie nicht verwenden möchten.
import {NextResponse} from "next/server"; const nodeName = process.env.NODE_NAME const redirect_REST_API = process.env.MGNL_API_REST_REDIRECTS const redirect_GRAPHQL_API = process.env.MGNL_API_GRAPHQL_REDIRECTS let storedRedirects = []; // Holt Umleitungen über REST oder GraphQL async function fetchRedirects() { // Diese Funktion holt Umleitungen und kann so konfiguriert werden, dass sie entweder den REST- oder den GraphQL-Endpunkt verwendet //return parseRedirectsREST(redirect_REST_API);
return parseRedirectsGRAPHQL(redirect_GRAPHQL_API) } // Analysiert von der REST-API abgerufene Weiterleitungen async function parseRedirectsREST(url) { const redirects = await fetchAPI(`${url}/?rootPage%5Blike%5D=${nodeName}%25`); return redirects.results.flatMap(parseRedirectItem); } // Parst Umleitungen, die von der GraphQL API geholt wurden async function parseRedirectsGRAPHQL(url) { const options = { method: "POST", headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: JSON.stringify({ query: ` { redirects (filter: "@rootPage LIKE '/nextjs-redirect-demo%'"){ redirect { from to { field internal custom } code } } } } }) }; const response = await fetchAPI(url, options); let parsedRed = response?.data?.redirects[0]?.redirect || []; return parsedRed.map(item => { item.to.internal = replaceNodeName(item.to.internal); return item; }); } // Analysiert ein einzelnes Umleitungselement function parseRedirectItem(item) { const rootPage = item.rootPage.replace(nodeName, ""); return item.redirect["@nodes"].map((redirectNode) => ({ from: rootPage + item.redirect[redirectNode].from, to: parseRedirectTo(item.redirect[redirectNode].to), code: item.redirect[redirectNode].code, })); } // Analysiert das 'bis'-Feld in einer Umleitung function parseRedirectTo(to) { return { field: to.field, custom: to.custom, internal: replaceNodeName(to.internal), }; } // Ersetzt nodeName in einer url function replaceNodeName(url) { return url?.replace(nodeName, "/")?.replace("//", "/"); } async function fetchAPI(url, options) { try { const response = await fetch(url, options); if (!response.ok) { throw new Error(`Ein Fehler ist aufgetreten: ${response.status}`); } return await response.json(); } catch (error) { console.error(error); return []; } } export async function middleware(request) { if (request.nextUrl.pathname === "/update-redirects" || storedRedirects?.length === 0) { storedRedirects = await fetchRedirects(); return NextResponse.next(); } const redirect = storedRedirects.find(r => r.from === request.nextUrl.pathname); if (redirect) { const url = redirect.to.field === 'internal' ? new URL(redirect.to.internal, request.url) : new URL(redirect.to.custom); return NextResponse.redirect(url, parseInt(redirect.code)); } return NextResponse.next(); }
Aktualisieren von Umleitungsdaten mit einem Webhook
Wie können wir eine Aktualisierung der Liste der Weiterleitungen in Next.js auslösen, wenn eine Weiterleitung in Magnolia erstellt oder geändert wird?
Wir können einen Webhook verwenden, der durch ein Published- und Unpublished-Ereignis ausgelöst wird. Gehen wir also zurück zum Verzeichnis Light Module, um die Webhook-Konfiguration zu erstellen.
/nextjs-redirect-lm/webhooks/webhookConfig_1.yaml
name: webhook1 url: http://localhost:3000/update-redirects method: GET enabled: true events: - name: contentPublished eventType: Published entity: redirect - name: contentUnpublished eventType: Unveröffentlicht Entität: redirect
Von nun an wird jedes Mal, wenn ein Redirect in der Content App veröffentlicht oder nicht veröffentlicht wird, der Webhook http://localhost:3000/update-redirects aufgerufen, um die Liste der Redirects in Next.js zu aktualisieren.
Überprüfung der Weiterleitungen
Öffnen Sie http://localhost:3000/contacts, um zu überprüfen, ob Sie zu http://localhost:3000/about-us/contacts weitergeleitet werden . Funktioniert es? Herzlichen Glückwunsch!
Um den Umleitungscode zu sehen, öffnen Sie die Entwicklertools und notieren Sie die Umleitung
Wenn Sie sich verlaufen haben oder direkt in den Code einsteigen wollen, finden Sie eine funktionierende Demo auf Git.
Ich hoffe, diese Anleitung hilft Ihnen! Sie können unsere gesamte Headless-Dokumentation hier einsehen.