Blog in Next.js mit Headless Oracle Content Management erstellen
Einführung
Next.js ist ein Open-Source-Web-Front-End-Entwicklungs-Framework für React, das Funktionen wie serverseitiges Rendering ermöglicht und statische Websites für React-basierte Webanwendungen generiert. Aber was geschieht, wenn Sie ein Content Management System (CMS) benötigen, um all Ihre Inhalte zu bedienen? Glücklicherweise bietet Oracle Content Management mit seinen umfassenden Headless-CMS-Funktionen eine anständige Lösung für Ihre Anforderungen an Inhaltsadministration und Governance.
In diesem Tutorial erstellen wir einen einfachen Blog in Next.js, indem wir Oracle Content Management als Headless CMS sowie sein Software Development Kit (SDK) für die Inhaltsbereitstellung in JavaScript nutzen. Dieses Next.js-Beispiel ist auf GitHub verfügbar.
Das Tutorial besteht aus drei Aufgaben:
- Oracle Content Management vorbereiten
- Blog in Next.js erstellen
- Vorbereitung der Anwendung auf das Deployment
Voraussetzungen
Bevor Sie mit diesem Tutorial fortfahren, sollten Sie zuerst die folgenden Informationen lesen:
Um diesem Tutorial zu folgen, benötigen Sie:
- ein Oracle Content Management-Abonnement
- ein Oracle Content Management-Account mit der Rolle "Content Administrator"
- ein Windows- oder Mac-Computer mit der Knotenversion 10 oder höher
Was wir bauen
Unser Blog besteht aus einer dreiseitigen Website, auf der Besucher Blogartikel in Themen kennenlernen können. Die erste Seite, die Homepage, besteht aus Branding (Firmenname und Logo), einigen Links und einer Liste von Blog-Themen.
Im Folgenden finden Sie den Endstatus unseres Tutorials, einem grundlegenden Blog von Next.js, der Inhalte aus Oracle Content Management verbraucht:
https://headless.mycontentdemo.com/samples/oce-nextjs-blog-sample
Die Homepage sieht am Ende dieses Tutorials aus:

Auf der zweiten Seite, der Themenseite, werden Vorschauen für jeden Blogartikel angezeigt, der zum Thema gehört. So sieht eine einzelne Themenseite aus:

Schließlich gibt die Artikelseite den letzten Blogartikel wieder, einschließlich Informationen zum Autor des Blogs. So sieht eine einzelne Artikelseite aus:

Um fortzufahren, benötigen Sie ein aktives Abonnement für Oracle Content Management und müssen mit der Rolle "Content Administrator" angemeldet sein.
Aufgabe 1: Oracle Content Management vorbereiten
Wenn noch keine Oracle Content Management-Instanz vorhanden ist, erfahren Sie unter Schnellstart, wie Sie sich für Oracle Cloud registrieren, eine Oracle Content Management-Instanz bereitstellen und Oracle Content Management als Headless CMS konfigurieren.
Für dieses Tutorial benötigen Sie zwei Möglichkeiten, um ein Contentmodell zu erstellen. Es ist ein herunterladbares Assetpaket verfügbar, das Ihr leeres Repository mit Inhaltstypen und zugehörigen Inhalten ausfüllt, oder Sie können Ihr eigenes Contentmodell und Ihren eigenen Inhalt erstellen.
So bereiten Sie Oracle Content Management vor:
- Erstellen Sie einen Kanal und ein Asset-Repository.
- Inhaltsmodell erstellen mit einer der beiden folgenden Methoden:
- Methode 1: Oracle Content Management Samples Asset Pack importieren
- Methode 2: Eigenes Contentmodell erstellen
Kanal- und Asset-Repository erstellen
Sie müssen zuerst einen Kanal und ein Asset-Repository in Oracle Content Management erstellen, damit Sie Inhalte veröffentlichen können.
So erstellen Sie einen Kanal und ein Asset-Repository in Oracle Content Management:
Melden Sie sich als Administrator bei der Oracle Content Management-Webbenutzeroberfläche an.
Wählen Sie im linken Navigationsmenü die Option Inhalt und anschließend Kanäle veröffentlichen aus der Auswahlliste im Seitenheader.

Klicken Sie in der oberen rechten Ecke auf Erstellen, um einen neuen Kanal zu erstellen. Benennen Sie den Kanal "OCEGettingStartedChannel" für die Zwecke dieses Tutorials, und behalten Sie den Zugriff öffentlich. Klicken Sie auf Speichern, um den Kanal zu erstellen.

Wählen Sie Inhalt im linken Navigationsmenü, und wählen Sie Repositorys aus der Auswahlliste im Seitenheader aus.

Klicken Sie in der oberen rechten Ecke auf Erstellen, um ein neues Asset-Repository zu erstellen. Benennen Sie das Asset-Repository "OCEGettingStartedRepository" für die Zwecke dieses Tutorials.

Wählen Sie im Feld Veröffentlichungskanäle den Kanal OCEGettingStartedChannel aus, um Oracle Content Management anzugeben, dass Inhalte im Repository OCEGettingStartedRepository im Kanal OCEGettingStartedChannel veröffentlicht werden können. Klicken Sie abschließend auf Speichern.

Contentmodelle erstellen
Als nächste Aufgabe wird ein Contentmodell erstellt. Sie haben zwei Möglichkeiten:
- Methode 1: Oracle Content Management Samples Asset Pack importieren
- Methode 2: Eigenes Contentmodell erstellen
Oracle Content Management Samples Asset Pack importieren
Sie können ein vorkonfiguriertes Oracle Content Management-Beispielassetspaket herunterladen, das alle erforderlichen Inhaltstypen und -assets für dieses Tutorial enthält. Gegebenenfalls können Sie auch ein eigenes Contentmodell erstellen, anstatt das Beispielassetspaket herunterzuladen.
Sie können eine Kopie des Inhalts, den wir in diesem Tutorial verwenden, aus dem Oracle Content Management Samples Asset Pack hochladen. Dadurch können Sie mit den Inhaltstypen experimentieren und den Inhalt ändern. Wenn Sie das Oracle Content Management Samples Asset Pack importieren möchten, können Sie das Assetpack-Archiv, OCESamplesAssetPack.zip, herunterladen und in ein Verzeichnis Ihrer Wahl extrahieren:
Laden Sie das Oracle Content Management Samples Asset Pack (OCESamplesAssetPack.zip) von der Seite Downloads von Oracle Content Management herunter. Extrahieren Sie die heruntergeladene ZIP-Datei an einen Speicherort auf Ihrem Computer. Nach der Extraktion enthält dieser Speicherort eine Datei namens OCEGettingStarted_data.zip.
Melden Sie sich als Administrator bei der Oracle Content Management-Webbenutzeroberfläche an.
Wählen Sie Inhalt im linken Navigationsmenü, und wählen Sie Repositorys aus der Auswahlliste im Seitenheader aus. Wählen Sie jetzt OCEGettingStartedRepository, und klicken Sie in der oberen Aktionsleiste auf die Schaltfläche Inhalt importieren.

Laden Sie OCEGettingStarted_data.zip von Ihrem lokalen Computer in den Ordner Dokumente hoch.

Wählen Sie nach dem Hochladen OCEGettingStarted_data.zip aus, und klicken Sie auf OK, um den Inhalt in das Asset-Repository zu importieren.

Nachdem der Inhalt erfolgreich importiert wurde, navigieren Sie zur Seite Anlagen, und öffnen Sie das Repository OCEGettingStartedRepository. Sie sehen, dass alle zugehörigen Bilder und Inhaltselemente jetzt dem Asset-Repository hinzugefügt wurden.

Klicken Sie oben links auf Alle auswählen und dann auf Veröffentlichen, um alle importierten Assets dem Veröffentlichungskanal hinzuzufügen, den Sie zuvor erstellt haben: OCEGettingStartedChannel.

Vor der Veröffentlichung müssen Sie alle Anlagen validieren. Fügen Sie zuerst OCEGettingStartedChannel als ausgewählten Kanal hinzu, und klicken Sie auf die Schaltfläche Validieren.

Nachdem die Assets validiert wurden, können Sie alle Assets im ausgewählten Kanal veröffentlichen, indem Sie oben rechts auf die Schaltfläche Veröffentlichen klicken.

Anschließend können Sie auf der Seite Anlagen sehen, dass alle Assets veröffentlicht wurden. (Sie können das Symbol über dem Assetnamen erkennen.)

Nach dem Import des Oracle Content Management Samples Asset Pack können Sie den Blog in Next.js erstellen.
Eigenes Contentmodell erstellen
Anstatt das Oracle Content Management Samples Asset Pack zu importieren, können Sie auch Ihr eigenes Contentmodell erstellen.
Für dieses Tutorial verwenden wir den Inhaltstyp "OCEGettingStartedHomePage", um die Homepage für unseren Blog zu erstellen. Diese Homepage besteht aus Branding (Firmenname und Logo), einigen URLs für Links und einer Liste der Blog-Themen, die auf der Seite enthalten sein sollten.

So erstellen Sie Inhaltstypen für das Contentmodell:
- Melden Sie sich als Administrator bei der Oracle Content Management-Webbenutzeroberfläche an.
- Wählen Sie im linken Navigationsmenü die Option Inhalt und anschließend Anlagentypen aus der Auswahlliste im Seitenheader.
- Klicken Sie auf Erstellen in der oberen rechten Ecke.
- Wählen Sie diese Option, um einen Inhaltstyp zu erstellen (kein digitaler Assettyp). Wiederholen Sie diesen Vorgang für alle erforderlichen Inhaltstypen.

Wir erstellen vier Inhaltstypen mit jeweils eigenen Feldern:
- OCEGettingStartedHomePage
- OCEGettingStartedTopic
- OCEGettingStartedAuthor
- OCEGettingStartedArticle
Der erste Inhaltstyp, OCEGettingStartedHomePage, sollte folgende Felder enthalten:
| Anzeigename | Feldtyp | erforderlich | Rechnername |
|---|---|---|---|
| Unternehmensname | Einzelwert-Textfeld | X | company_name |
| Firmenlogo | Einzelwert-Textfeld | X | company_logo |
| Themen | Referenzfeld mit mehreren Werten | X | Themen |
| Kontakt-URL | Einzelwert-Textfeld | X | contact_url |
| Info URL | Einzelwert-Textfeld | X | about_url |
Die OCEGettingStartedHomePage-Inhaltstypdefinition sollte wie folgt aussehen:

Der zweite Inhaltstyp OCEGettingStartedTopic muss folgendes Feld enthalten:
| Anzeigename | Feldtyp | erforderlich | Rechnername |
|---|---|---|---|
| Thumbnail | Bildfeld mit einem Wert | X | Thumbnail |
Der Inhaltstyp OCEGettingStartedTopic sollte wie folgt aussehen:

Der dritte Inhaltstyp OCEGettingStartedAuthor sollte folgende Felder enthalten:
| Anzeigename | Feldtyp | erforderlich | Rechnername |
|---|---|---|---|
| Avatar | Bildfeld mit einem Wert | X | Avatar |
Der Inhaltstyp OCEGettingStartedAuthor sollte wie folgt aussehen:

Der vierte und letzte Inhaltstyp OCEGettingStartedArticle sollte folgende Felder enthalten:
| Anzeigename | Feldtyp | erforderlich | Rechnername |
|---|---|---|---|
| Veröffentlichungsdatum | Feld mit einem Wert | X | published_name |
| Autor | Referenzfeld mit einem Wert | X | Autor |
| Bild | Bildfeld mit einem Wert | X | Image |
| Bildunterschrift | Einzelwert-Textfeld | X | image_caption |
| Artikelinhalt | Großtextfeld mit einem Wert | X | article_content |
| Thema | Referenzfeld mit einem Wert | X | Thema |
Der Inhaltstyp OCEGettingStartedArticle sollte wie folgt aussehen:

Nachdem Sie Ihre Inhaltstypen erstellt haben, können Sie diese Inhaltstypen dem zuvor erstellten Repository OCEGettingStartedRepository hinzufügen:
- Melden Sie sich als Administrator bei der Oracle Content Management-Webbenutzeroberfläche an.
- Navigieren Sie zu OCEGettingStartedRepository.
- Bearbeiten Sie das Repository, und geben Sie unter Anlagentypen alle vier neu erstellten Inhaltstypen an. Klicken Sie auf Speichern, um die Änderungen zu speichern.

Nachdem Sie die Inhaltstypen zum Repository hinzugefügt haben, können Sie das Repository OCEGettingStartedRepository auf der Seite Anlagen öffnen und Ihre Inhaltselemente für alle Inhaltstypen erstellen.

Aufgabe 2: Blog in Next.js erstellen
Um unsere Oracle Content Management-Inhalte in einer serverseitigen wiedergegebenen Next.js-Anwendung zu verbrauchen, können wir das Next.js-Blogbeispiel verwenden, das als Open-Source-Repository auf GitHub verfügbar ist.
Hinweis: Beachten Sie, dass die Verwendung des Beispiels "Next.js" optional ist. In diesem Tutorial erhalten Sie einen schnellen Einstieg. Sie können auch Ihre eigene Next.js-Anwendung erstellen.
So erstellen Sie den Blog in Next.js:
- Beispiel-Repository klonen und Abhängigkeiten installieren
- Next.js-Anwendung konfigurieren
- Mit dem Oracle Content Management Content-SDK arbeiten
- Content-SDK zum Abrufen von Inhalt verwenden
Beispiel-Repository klonen und Abhängigkeiten installieren
Das Next.js-Blogbeispiel ist als Open-Source-Repository in GitHub verfügbar.
Zunächst müssen Sie das Beispiel von GitHub auf Ihren lokalen Computer klonen und Ihr Verzeichnis in das Repository-Root ändern:
git clone https://github.com/oracle/oce-nextjs-blog-sample.git
cd oce-nextjs-blog-sample
Nachdem Sie jetzt über Ihre Codebasis verfügen, müssen Sie Abhängigkeiten für die Anwendung herunterladen. Führen Sie den folgenden Befehl aus dem Root-Verzeichnis aus:
npm install
Next.js-Anwendung konfigurieren
In diesem Next.js-Blogbeispiel müssen Sie einige Informationen konfigurieren, damit Ihr Oracle Content Management Content-SDK (und andere Anforderungen) die richtige Instanz-URL und API-Version mit dem richtigen Kanaltoken ansprechen kann. Diese Werte werden in script/server-config-utils.js verwendet, um einen neuen Zustellungsclient zu instanziieren.
Diese Anwendung verwendet eine .env.local-Datei, die von Next.js gelesen und dem Code innerhalb der Anwendung mit process.env zur Verfügung gestellt wird.
Öffnen Sie die .env.local-Datei in einem Texteditor. Folgende Informationen werden angezeigt:
# The connection details for the Oracle Content Management server to be used for this application
SERVER_URL=https://samples.mycontentdemo.com
API_VERSION=v1.1
CHANNEL_TOKEN=47c9fb78774d4485bc7090bf7b955632
Ändern Sie die einzelnen Schlüssel/Wert-Paare entsprechend Ihrer Instanz-URL, der gewünschten API-Version und dem mit Ihrem Veröffentlichungskanal verknüpften Kanaltoken. Der Kanal für dieses Tutorial ist OCEGettingStartedChannel.
Mit dem Oracle Content Management Content-SDK arbeiten
Oracle Content Management bietet ein SDK, mit dem Sie Inhalte in Ihren Anwendungen erkennen und verwenden können. Das SDK wird als NPM-Modul veröffentlicht und das Projekt wird auf GitHub gehostet.
Weitere Informationen zum SDK finden Sie hier.
Das SDK wurde als Laufzeitabhängigkeit dieses Projekts in der Datei package.json registriert.
Content-SDK zum Abrufen von Inhalt verwenden
Wir können das Content-SDK jetzt nutzen, um Inhalte abzurufen, damit wir es in unserer Next.js-Anwendung wiedergeben können.
Der Skriptordner enthält den Code zum Abrufen von Daten aus Oracle Content Management mit dem Content-SDK.
Die Datei script/server-config-utils.js importiert das Content SDK und erstellt dann einen Zustellungsclient mit der in .env.local angegebenen Konfiguration.
Der folgende Befehl importiert das SDK:
import { createDeliveryClient, createPreviewClient } from '@oracle/content-management-sdk';Mit dem folgenden Befehl wird der Delivery Client erstellt:
return createDeliveryClient(serverconfig);Die Datei script/services.js enthält den gesamten Code zum Abrufen von Daten für die Anwendung. Für jede Seitenkomponente in der Anwendung gibt es eine Hauptfunktion, um alle Daten für diese Seite abzurufen.
Für die Wiedergabe der Images stellt services.js eine Helper-Methode bereit, mit der das Quellset für eine Anlage abgerufen wird, die aus den Wiedergaben für die Anlage erstellt wurde.
function getSourceSet(asset) {
const urls = {};
urls.srcset = '';
urls.jpgSrcset = '';
if (asset.fields && asset.fields.renditions) {
asset.fields.renditions.forEach((rendition) => {
addRendition(urls, rendition, 'jpg');
addRendition(urls, rendition, 'webp');
});
}
// add the native rendition to the srcset as well
urls.srcset += `${asset.fields.native.links[0].href} ${asset.fields.metadata.width}w`;
urls.native = asset.fields.native.links[0].href;
urls.width = asset.fields.metadata.width;
urls.height = asset.fields.metadata.height;
return urls;
}Homepage-Daten
Für die Homepage sind mehrere Datenaufrufe erforderlich, um alle Daten abzurufen:
- Zuerst fragen wir nach Elementen im Kanal ab, der in .env.local angegeben ist.
- Für jedes Thema werden die Details abgerufen.
Öffnen Sie script/services.js, und suchen Sie die Funktion getTopicsListPageData(), die alle Daten für die Homepage abruft.
export function getTopicsListPageData() {
const client = getDeliveryClient();
return fetchHomePage(client)
.then((data) => (
getRenditionURLs(client, data.logoID)
.then((renditionUrls) => {
data.companyThumbnailRenditionUrls = renditionUrls;
return data;
})
));
}Die Funktion fetchHomePage(), die von der Funktion getTopicsListPageData() aufgerufen wird, ruft alle Elemente im Kanal ab. Dadurch werden die Logo-ID, der Firmenname, die Informations- und Kontakt-URLs und eine Themenliste abgerufen.
function fetchHomePage(client) {
return client.queryItems({
q: '(type eq "OCEGettingStartedHomePage" AND name eq "HomePage")',
}).then((data) => {
const logoID = data.items[0].fields.company_logo.id;
const title = data.items[0].fields.company_name;
const aboutUrl = data.items[0].fields.about_url;
const contactUrl = data.items[0].fields.contact_url;
const { topics } = data.items[0].fields;
const promises = [];
topics.forEach((origTopic) => {
// add a promise to the total list of promises to get the full topic details
promises.push(
fetchTopic(client, origTopic.id)
.then((topic) => topic),
);
});
// execute all the promises returning a single dimension array of all
// of the topics and the other home page data
return Promise.all(promises)
.then((allTopics) => (
{
logoID,
companyTitle: title,
aboutUrl,
contactUrl,
topics: flattenArray(allTopics),
}
)).catch((error) => logError('Fetching topics failed', error));
}).catch((error) => logError('Fetching home page data failed', error));
}Die Funktion fetchTopic() wird dann für jede Themen-ID aufgerufen, um die vollständigen Themendetails abzurufen.
function fetchTopic(client, topicId) {
return client.getItem({
id: topicId,
expand: 'fields.thumbnail',
}).then((topic) => {
topic.renditionUrls = getSourceSet(topic.fields.thumbnail);
return topic;
}).catch((error) => logError('Fetching topic failed', error));
}getTopicsListPageData() ruft auch getRenditionURLs() auf, um die URL des wiederzugebenden Bildes abzurufen.
function getRenditionURLs(client, identifier) {
return client.getItem({
id: identifier,
expand: 'fields.renditions',
}).then((asset) => getSourceSet(asset))
.catch((error) => logError('Fetching Rendition URLs failed', error));
}Themenseitendaten
Next.js verwendet die statische Sitegenerierung, um jede Seite in der Anwendung vorab wiederzugeben. Die Pfade für jede Themenseite enthalten die Themen-ID. Öffnen Sie Skripte/services.js, und suchen Sie die Funktion fetchTopicIds(), mit der alle Themen-IDs abgerufen werden.
export function fetchTopicIds() {
const client = getDeliveryClient();
return client.queryItems({
q: '(type eq "OCEGettingStartedHomePage" AND name eq "HomePage")',
}).then((data) => {
const { topics } = data.items[0].fields;
const topicIds = topics.map(
(topic) => topic.id,
);
return topicIds;
}).catch((error) => logError('Fetching topic ids failed', error));
}Eine Themenseite empfängt eine Themen-ID und erfordert mehrere Datenaufrufe, um alle zugehörigen Daten abzurufen:
- Namen des Themas abrufen
- Alle Artikel für das angegebene Thema abrufen.
- Rufen Sie für jeden Artikel die zugehörigen Auslieferungs-URLs ab.
Suchen Sie die Funktion fetchTopicName(topicId), mit der der Name des Themas abgerufen wird.
export function fetchTopicName(topicId) {
const client = getDeliveryClient();
return client.getItem({
id: topicId,
}).then((topic) => topic.name)
.catch((error) => logError('Fetcvhing topic name failed', error));
}Suchen Sie die Funktion fetchTopicArticles(topicId), die die Artikeldaten für die Themaseite abruft.
export function fetchTopicArticles(topicId) {
const client = getDeliveryClient();
return client.queryItems({
q: `(type eq "OCEGettingStartedArticle" AND fields.topic eq "${topicId}")`,
orderBy: 'fields.published_date:desc',
}).then((data) => {
const promises = [];
const articles = data.items;
articles.forEach((article) => {
// add a promise to the total list of promises to get the article url
promises.push(
getRenditionURLs(client, article.fields.image.id)
.then((renditionUrls) => {
article.renditionUrls = renditionUrls;
// Note: the spread operator is used here so that we return a top level
// object, rather than a value which contains the object
// i.e we return
// {
// field1: 'value', field2 : "value", etc
// },
// rather than
// {
// name: {
// field1: 'value', field2 : "value", etc
// }
// }
return {
...article,
};
}),
);
});
// execute all the promises and return all the data
return Promise.all(promises)
.then((allArticles) => ({
topicId,
articles: flattenArray(allArticles),
}));
}).catch((error) => logError('Fetching topic articles failed', error));
}Die fetchTopicArticles()-Methode verwendet auch die zuvor ermittelte getRenditionURLs(), um das Bild für den Artikel abzurufen.
Artikelseitendaten
Die Pfade für jede Artikelseite enthalten die Artikel-ID. Öffnen Sie die Skripts/services.js, und suchen Sie die Funktion fetchAllArticlesSimple(), mit der alle Artikel-IDs abgerufen werden, die bei der Vorabwiedergabe jeder Artikelseite verwendet werden.
export function fetchAllArticlesSimple() {
const client = getDeliveryClient();
return fetchTopicIds()
.then((topicIds) => {
const promises = [];
topicIds.forEach((topicId) => {
// add a promise to the total list of promises to get the article url
promises.push(
fetchTopicArticlesSimple(client, topicId)
.then((data) => {
const { items } = data;
const articles = items.map((item) => (
{
id: item.id,
name: item.name,
}
));
return articles;
}),
);
});
// execute all the promises and return all the data
return Promise.all(promises)
.then((allArticles) => flattenArray(allArticles));
}).catch((error) => logError('Fetching basic information for all articles failed', error));
}fetchAllArticlesSimple() ruft fetchTopicArticlesSimple() auf, um eine vereinfachte Liste der Artikel abzurufen.
function fetchTopicArticlesSimple(client, topicId) {
return client.queryItems({
q: `(type eq "OCEGettingStartedArticle" AND fields.topic eq "${topicId}")`,
orderBy: 'fields.published_date:desc',
}).then((data) => data)
.catch((error) => logError('Fetching basic information for topic articles failed', error));
}Eine Artikelseite erhält eine Artikel-ID und erfordert mehrere Datenaufrufe, um alle zugehörigen Daten abzurufen:
- Rufen Sie die Artikeldetails für den angegebenen Artikel ab.
- Rufen Sie für jeden Artikel die zugehörigen Auslieferungs-URLs ab.
Suchen Sie die Funktion fetchArticleDetails(articleId), die die Daten für die Artikelseite abruft. Die Methode verwendet die Funktion getRenditionURL(), die das Bild für den Artikel abruft und außerdem die Funktion getMediumRenditionURL() verwendet, um das Bild für den Autor abzurufen.
export function fetchArticleDetails(articleId) {
const client = getDeliveryClient();
return client.getItem({
id: articleId,
expand: 'fields.author,fields.image',
}).then((article) => {
const { fields } = article;
const title = fields.author.name;
const date = fields.published_date;
const content = fields.article_content;
const imageCaption = fields.image_caption;
const { topic } = fields;
const { name } = article;
const renditionUrls = getSourceSet(article.fields.image);
const avatarID = article.fields.author.fields.avatar.id;
// Get the author's avatar image
return getRenditionURLs(client, avatarID)
.then((authorRenditionUrls) => (
// return an object with just the data needed
{
id: articleId,
name,
title,
date,
content,
imageCaption,
renditionUrls,
authorRenditionUrls,
topicId: topic.id,
topicName: topic.name,
}
));
}).catch((error) => logError('Fetching article details failed', error));
}Die fetchArticleDetails()-Methode verwendet auch die zuvor angezeigte getRenditionURLs(), um das Avatarbild abzurufen.
Nachdem unsere Datenabfragen vorliegen, können wir die Antworten in unseren Next.js-Komponenten gerendern.
Next.js-Komponenten
Next.js basiert auf React und React verwendet eine Technologie, die als JSX bezeichnet wird. Dabei handelt es sich um eine HTML-ähnliche Syntaxerweiterung für JavaScript, um den Inhalt wiederzugeben. Auch wenn Sie reinen JavaScript schreiben können, um Daten aus Oracle Content Management wiederzugeben, wird dringend empfohlen, JSX zu verwenden.
Die Blog-Anwendung unterteilt jede Seite in eine Reihe kleinerer Komponenten.
Die nächsten Abschnitte bieten einen Überblick darüber, wie Next.js unsere Anwendung in jeder unserer Komponenten wiedergibt:
- Seitenordner
- Indexkomponente
- Headerkomponente
- TopicsListItem-Komponente
- ArticleListPage-Komponente
- ArticesListItem-Komponente
- ArticleDetailsPage-Komponente
- Navigationspfade und Navigationspfadkomponenten
Seitenordner
Auf unserer Website möchten wir drei Routen anbieten:
- Die Homepage, die aus der Themenliste besteht
- Die Themenseite, auf der alle Artikel für das ausgewählte Thema angezeigt werden
- Die einzelne Artikelseite, die den ausgewählten Artikel anzeigt
Jede Seite im Seitenverzeichnis Next.js wird als Route für die Anwendung behandelt.
Indexkomponente
Die Homepage besteht aus einer Liste mit einzelnen Themen. Es wird von der Indexkomponente unter pages/index.jsx wiedergegeben.
Die Komponente importiert die API, um Daten aus der Datei services.js abzurufen.
import { getTopicsListPageData } from '../scripts/services';In getStaticProps(), die während der Erstellungszeit aufgerufen wird, ruft die Komponente alle Daten ab, die zur Wiedergabe der Homepage erforderlich sind.
export async function getStaticProps() {
const data = await getTopicsListPageData();
return { props: { data } };
}Headerkomponente
Die Indexkomponente verwendet die Kopfdatenkomponente, um den Firmentitel, das Firmenlogo und die Links "Kontakt"/"Info" anzuzeigen.
Es befindet sich in src/components/Header.jsx und empfängt alle zugehörigen Daten als Eigenschaften. Es werden keine zusätzlichen Daten vom Server abgerufen.
TopicsListItem-Komponente
Die Indexkomponente verwendet die Komponente TopicsListItem, um das einzelne Thema in der Liste anzuzeigen.
Die Komponente TopicsListItem, die sich unter src/components/TopicsListItem.jsx befindet, empfängt alle zugehörigen Daten als Eigenschaften. Es werden keine zusätzlichen Daten vom Server abgerufen.
ArticleListPage-Komponente
Auf der Seite "Thema" werden die Artikel im Thema angezeigt, deren ID an die Komponente der URL übergeben wird. Sie wird von der Komponente ArticleListPage in den Seiten/Artikel/[id].jsx wiedergegeben.
Die Komponente importiert die API, um Daten aus der Datei services.js abzurufen.
import { fetchTopicIds, fetchTopicName, fetchTopicArticles } from '../../scripts/services';Die URLs für die Seite "Themen" sind dynamische URLs, die die Themen-ID als Pfad enthalten. Beispiel-URL-Pfade sind
- /articles/topicId1
- /articles/topicId2
- /articles/topicId3
Wenn Next.js die statische Sitegenerierung für Seiten mit dynamischen URLs verwendet, ruft es getStaticPaths() auf, um alle Pfade für diese Seite abzurufen.
export async function getStaticPaths() {
const topicIds = await fetchTopicIds();
// Generate the paths we want to pre-render based on posts
const paths = topicIds.map((topicId) => ({
params: { id: topicId },
}));
return {
paths,
fallback: false,
};
}Mit der Funktion getStaticProps() werden die Daten für eine einzelne Instanz der Seite "Themen" abgerufen. Die Themen-ID wird aus dem Parameter abgerufen, der an die Methode übergeben wird. Mit der Themen-ID werden dann alle für diese Seite erforderlichen Daten abgerufen.
export async function getStaticProps(context) {
const { params } = context;
const { id } = params;
const [data, topicName] = await Promise.all([fetchTopicArticles(id), fetchTopicName(id)]);
return {
props: {
topicId: id,
topicName,
data,
},
};
}ArticesListItem-Komponente
Die Komponente ArticleListPage verwendet die Komponente ArticlesListItem, um die einzelnen Artikel in der Liste anzuzeigen.
Die Komponente ArticlesListItem befindet sich in src/components/ArticlesListItem.jsx und empfängt alle zugehörigen Daten als Eigenschaften. Es werden keine zusätzlichen Daten vom Server abgerufen.
ArticleDetailsPage-Komponente
Auf der Seite "Artikel" werden Details des Artikels angezeigt, dessen ID an die URL übergeben wird. Sie wird von der Komponente ArticleDetailsPage in den Seiten/Artikel/[id].jsx wiedergegeben.
Die Komponente importiert die API, um Daten aus der Datei services.js abzurufen.
import { fetchAllArticlesSimple, fetchArticleDetails } from '../../scripts/services';Die URLs für die Artikelseite sind dynamische URLs, die die Artikel-ID als Pfad enthalten. Beispiel-URL-Pfade sind
- /article/articleId1
- /article/articleId2
- /article/articleId3
Wenn Next.js die statische Sitegenerierung für Seiten mit dynamischen URLs verwendet, ruft es getStaticPaths() auf, um alle Pfade für diese Seite abzurufen.
export async function getStaticPaths() {
const articles = await fetchAllArticlesSimple();
// Generate the paths we want to pre-render based on posts
return {
paths: articles.map((article) => ({
params: { id: article.id },
})),
fallback: true,
};
}Mit der Funktion getStaticProps() werden die Daten für eine einzelne Instanz der Artikelseite abgerufen. Die Artikel-ID wird aus dem an das Verfahren übergebenen Parameter ermittelt. Die Artikel-ID wird dann verwendet, um alle für diese Seite erforderlichen Daten abzurufen.
export async function getStaticProps(context) {
const { params } = context;
const { id } = params;
const data = await fetchArticleDetails(id);
return {
props: {
data,
},
};
}Navigationspfade und Navigationspfadkomponenten
Sowohl die Komponenten "Index" als auch "ArticleDetailsPage" verwenden die Komponenten "Breadcrumbs" und "Breadcrumb", um die Navigationspfade oben auf der Seite anzuzeigen, sodass der Benutzer zur Seite "Thema" oder zur Homepage zurückkehren kann. Beide Komponenten erhalten alle ihre Daten als Eigenschaften. Sie erhalten keine zusätzlichen Daten vom Server.
Aufgabe 3: Anwendung auf Deployment vorbereiten
Nachdem wir unsere Next.js-Blog-Website erstellt haben, müssen wir sie auf einem lokalen Entwicklungsserver sehen, damit wir Probleme debuggen und die Anwendung vor ihrem Go-Live in der Vorschau anzeigen können.
Bereiten Sie die Anwendung in zwei Schritten vor:
- Lokalen Entwicklungsserver hochfahren
- Verwenden von Skripten zum Erstellen und Ausführen der Anwendung in Entwicklung und Produktion
Lokalen Entwicklungsserver hochfahren
Sie können einen Entwicklungsserver lokal starten, indem Sie den folgenden Befehl ausführen.
npm run dev
Öffnen Sie dann Ihren Browser zu http://localhost:3000, um Ihre Site in Aktion anzuzeigen.
Hinweis: Dadurch werden die Seiten nicht vorab wiedergegeben. Im nächsten Abschnitt wird beschrieben, wie Sie die Seiten im Voraus anzeigen.
Verwenden von Skripten zum Erstellen und Ausführen der Anwendung in Entwicklung und Produktion
Für die Produktion wird das Build-Skript verwendet, um die Site statisch zu generieren.
npm run build
Mit dem Startskript wird ein Node.js-Server gestartet, der die statisch generierten Seiten bedient.
npm run start
Blog in Next.js mit Headless Oracle Content Management erstellen
F49322-01
Oktober 2021
Copyright © 2021, Oracle and/or its affiliates.
Hauptverfasser: Oracle Corporation