Blog mit Headless Oracle Content Management in Angular erstellen

Einführung

Angular ist eine Plattform zum Erstellen von mobilen und Desktop-Webanwendungen. 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 Angular, indem wir Oracle Content Management als Headless-CMS sowie sein Software Development Kit (SDK) für die Inhaltsbereitstellung in JavaScript nutzen. Diese Angularprobe ist in GitHub verfügbar.

Das Tutorial besteht aus drei Schritten:

  1. Oracle Content Management vorbereiten
  2. Blog in Angular erstellen
  3. 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:

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 englischsprachigen Blog, der Inhalte aus Oracle Content Management verbraucht:

https://headless.mycontentdemo.com/samples/oce-angular-blog-sample

Die Homepage sieht am Ende dieses Tutorials aus:

Diese Abbildung zeigt die Homepage für die Cafe Supremo-Demosite mit einer Liste der verfügbaren Themen.

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

Diese Abbildung zeigt eine Themenseite mit dem Namen "Rezepte" mit einer Liste der verfügbaren Artikel für dieses Thema.

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

Diese Abbildung zeigt eine einzelne Artikelseite mit Inhalt und Autorreferenz.

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:

  1. Erstellen Sie einen Kanal und ein Asset-Repository.
  2. Inhaltsmodell erstellen mit einer der beiden folgenden Methoden:

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:

  1. Melden Sie sich als Administrator bei der Oracle Content Management-Webbenutzeroberfläche an.

  2. Wählen Sie im linken Navigationsmenü die Option Inhalt und anschließend Kanäle veröffentlichen aus der Auswahlliste im Seitenheader.

    Diese Abbildung zeigt die Option "Veröffentlichungskanäle veröffentlichen", die im Dropdown-Menü im Header der Seite "Inhalt" ausgewählt wurde.

  3. 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.

    Diese Abbildung zeigt den Bereich "Veröffentlichungskanaldefinition" mit "OCEGettingStartedChannel" im Feld "Kanalname".

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

    Diese Abbildung zeigt die Option "Repositorys", die im Dropdown-Menü im Header der Seite "Inhalt" ausgewählt wurde.

  5. 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.

    Diese Abbildung zeigt den Bereich "Repository-Definition" mit "OCEGettingStartedRepository" im Feld "Repository-Name".

  6. 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.

    Diese Abbildung zeigt den Bereich "Repository-Definition" mit "OCEGettingStartedChannel" im Feld "Veröffentlichungskanäle".

Contentmodelle erstellen

Im nächsten Schritt erstellen Sie ein Contentmodell. Sie haben zwei Möglichkeiten:

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:

  1. 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.

  2. Melden Sie sich als Administrator bei der Oracle Content Management-Webbenutzeroberfläche an.

  3. 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.

    Diese Abbildung zeigt die Seite "Repositorys", wobei das Element OCEGettingStartedRepository ausgewählt ist.

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

    Diese Abbildung zeigt den Bildschirm zur Uploadbestätigung für die OCEGettingStarted_data.zip-Datei.

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

    Diese Abbildung zeigt die ausgewählte OCEGettingStarted_data.zip-Datei mit aktivierter Schaltfläche "OK".

  6. 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.

    Diese Abbildung zeigt das OCEGettingStartedRepository-Repository mit allen Assets, die gerade importiert wurden.

  7. 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.

    Diese Abbildung zeigt das Repository OCEGettingStartedRepository mit allen ausgewählten Assets und der Option "Veröffentlichen" in der Aktionsleiste.

  8. 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.

    Diese Abbildung zeigt die Seite "Validierungsergebnisse", auf der der Kanal OCEGettingStartedChannel im Feld "Kanäle" hinzugefügt wurde, alle zu validierenden Assets und die Schaltfläche "Validieren" aktiviert sind.

  9. 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.

    Diese Abbildung zeigt die Seite "Validierungsergebnisse", auf der der Kanal OCEGettingStartedChannel im Feld "Kanäle" hinzugefügt, alle Assets validiert und die Schaltfläche "Veröffentlichen" aktiviert ist.

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.)

Diese Abbildung zeigt die Seite "Anlagen" mit allen Assets.

Nachdem Sie das Oracle Content Management Samples Asset Pack importiert haben, können Sie mit dem Blog in Angular erstellen beginnen.

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.

Diese Abbildung zeigt die Homepage für die Cafe Supremo-Demosite.

So erstellen Sie Inhaltstypen für das Contentmodell:

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

Diese Abbildung zeigt das Dialogfeld "Anlagentyp erstellen" in der Webbenutzeroberfläche von Oracle Content Management.

Wir erstellen vier Inhaltstypen mit jeweils eigenen Feldern:

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:

Diese Abbildung zeigt die Definition für den Inhaltstyp "OCEGettingStartedHomePage". Sie enthält folgende Datenfelder: Firmenname, Unternehmenslogo, Themen, Kontakt-URL und Info-URL.

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:

Diese Abbildung zeigt die Definition für den Inhaltstyp "OCEGettingStartedTopic". Er enthält dieses Datenfeld: Miniaturbild.

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:

Diese Abbildung zeigt die Definition für den Inhaltstyp "OCEGettingStartedAuthor". Es enthält dieses Datenfeld: Avatar.

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:

Diese Abbildung zeigt die Definition für den Inhaltstyp "OCEGettingStartedArticlePage". Sie enthält folgende Datenfelder: Veröffentlichungsdatum, Autor, Bild, Bildbeschriftung, Artikelinhalt und Thema.

Nachdem Sie Ihre Inhaltstypen erstellt haben, können Sie diese Inhaltstypen dem zuvor erstellten Repository OCEGettingStartedRepository hinzufügen:

  1. Melden Sie sich als Administrator bei der Oracle Content Management-Webbenutzeroberfläche an.
  2. Navigieren Sie zu OCEGettingStartedRepository.
  3. Bearbeiten Sie das Repository, und geben Sie unter Anlagentypen alle vier neu erstellten Inhaltstypen an.
  4. Klicken Sie auf Speichern, um die Änderungen zu speichern.

Diese Abbildung zeigt die Seite "Repository bearbeiten" in Oracle Content Management mit den vier neu erstellten Inhaltstypen, die mit dem Repository OCEGettingStartedRepository verknüpft sind.

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.

Diese Abbildung zeigt Inhaltselemente auf der Seite "Anlagen" in der Oracle Content Management-Webbenutzeroberfläche mit Optionen auf der linken Seite für Collections, Kanäle, Sprachen, Typen, Auswahl von Inhaltselementen und Status.

Aufgabe 2: Blog in Angular erstellen

Um unsere Oracle Content Management-Inhalte in einer Angular-Anwendung zu verbrauchen, können wir das Angular-Blogbeispiel verwenden, das als Open-Source-Repository auf GitHub verfügbar ist.

Hinweis: Beachten Sie, dass die Verwendung der Angularprobe optional ist. Wir verwenden sie in diesem Tutorial, um Ihnen einen schnellen Einstieg zu ermöglichen. Sie können auch Ihre eigene Angular-Anwendung erstellen, beispielsweise ein Gerüst der Angular CLI mit zusätzlicher serverseitiger Rendering-Unterstützung über die Angular CLI.

So erstellen Sie den Blog in Angular:

  1. Beispiel-Repository klonen und Abhängigkeiten installieren
  2. Angularen Anwendungen konfigurieren
  3. Mit dem Oracle Content Management Content-SDK arbeiten
  4. Content-SDK zum Abrufen von Inhalt verwenden

Beispiel-Repository klonen und Abhängigkeiten installieren

Das Angular-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-angular-blog-sample.git
    cd oce-angular-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

Angular Application konfigurieren

In diesem Angular-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 src/scripts/server-config-utils.js verwendet, um einen neuen Zustellungsclient zu instanziieren.

Diese Anwendung verwendet eine .env-Datei, die von Webpack gelesen wird, wenn sie die Client- und Serveranwendungen bündelt. Mit webpack.DefinePlugin können alle aus der .env-Datei gelesenen Werte überall in der Anwendung zur Verfügung gestellt werden.

Öffnen Sie die .env-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 Angular-Anwendung wiedergeben können.

Das Inhalts-SDK verwendet ein DeliveryClient-Objekt, um den Endpunkt anzugeben. Sie können alle Anforderungen mit diesem Clientobjekt ausführen.

Der Ordner " src/scripts" enthält den Code zum Abrufen von Daten aus Oracle Content Management mit dem Inhalts-SDK.

Die Datei src/scripts/server-config-utils.js importiert das Content-SDK und erstellt dann einen Zustellungsclient mit der in .env 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);

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;
    }

Die Datei src/scripts/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.

Homepage-Daten

Für die Homepage sind mehrere Datenaufrufe erforderlich, um alle Daten abzurufen:

  1. Zuerst fragen wir nach Elementen im Kanal ab, der in .env angegeben ist.
  2. Für jedes Thema werden die Details abgerufen.

Öffnen Sie src/scripts/services.js, und suchen Sie die Funktion getTopicsListPageData(), die alle Daten für die Homepage abruft.

export function getTopicsListPageData() {
      const client = getClient();
    
      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

Die Themenseite erhält eine Themen-ID und erfordert mehrere Datenaufrufe, um alle zugehörigen Daten abzurufen:

  1. Alle Artikel für das angegebene Thema abrufen.
  2. Rufen Sie für jeden Artikel die zugehörigen Auslieferungs-URLs ab.

Öffnen Sie src/scripts/services.js, und suchen Sie die Funktion fetchTopicArticles(topicId), mit der alle Daten für die Themaseite abgerufen werden.

export function fetchTopicArticles(topicId) {
      const client = getClient();
      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
        // 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 Artikelseite erhält eine Artikel-ID und erfordert mehrere Datenaufrufe, um alle zugehörigen Daten abzurufen:

  1. Rufen Sie die Artikeldetails für den angegebenen Artikel ab. Rufen Sie für jeden Artikel die zugehörigen Auslieferungs-URLs ab.
  2. Rufen Sie die Rendition-URLs für den Avatar des Autors ab.

Öffnen Sie src/scripts/services.js, und suchen Sie die Funktion fetchArticleDetails(articleId), die die Daten für die Artikelseite abruft.

export function fetchArticleDetails(articleId) {
      const client = getClient();
      return client.getItem({
        id: articleId,
        expand: 'fields.author,fields.image',
      }).then((article) => {
        const title = article.fields.author.name;
        const date = article.fields.published_date;
        const content = article.fields.article_content;
        const imageCaption = article.fields.image_caption;
        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,
            }
          ));
      }).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 zahligen Komponenten wiedergeben.

Clientseitiges und serverseitiges Rendering – Vergleich

Mit Client-seitigem Rendering (CSR) ist der Client für das Erstellen und Rendering des Inhalts einer Webseite mit JavaScript verantwortlich. Bei serverseitigem Rendering (SSR) wird die gesamte Seite auf dem Server erstellt, und eine vollständige Webseite wird an den Client zurückgegeben.

Wenn die Webseite vom Server im clientseitigen Rendering angefordert wird, enthält das zurückgegebene HTML-Dokument Skeleton HTML und keinen tatsächlichen Inhalt. Sie enthält eine Referenz auf ein JavaScript-Bundle, das der Client dann vom Server anfordert. Nach Erhalt dieses Bündels führt der Client das JavaScript aus und füllt die Webseite aus. Bis der Client die Ausführung von JavaScript abgeschlossen hat, wird dem Benutzer eine leere Webseite angezeigt. Ein Nachteil von Client-seitigen gerenderten Anwendungen besteht darin, dass, wenn einige Web-Crawler die Site indexieren, kein tatsächlicher Inhalt vorhanden ist.

Bei serverseitigem Rendering (SSR) wird die gesamte Seite auf dem Server erstellt, und eine vollständige Webseite wird an den Client zurückgegeben. Der Vorteil ist, dass Web-Crawler den gesamten Inhalt auf der Webseite indizieren können.

Angular Server-seitiges Rendering

Der Fluss der Angular-Bloganwendung lautet wie folgt:

  1. Der Client fordert eine Anforderung an den Server für eine bestimmte Route an.
  2. Der Express-Server empfängt die Anforderung.
  3. Der Express-Server übergibt alle Clientanforderungen für Seiten an die Express Engine von Angular Univeral
  4. Die Express Engine von Angular Univeral erstellt eine HTML-Vorlagendatei und füllt sie mit folgenden Daten auf:
    1. Das Markup für die angegebene Route
    2. Die Routendaten werden serialisiert
    3. Verweise auf alle Stylesheets
    4. Verweise auf JavaScript-Bundles, die auf dem Client ausgeführt werden sollen
  5. Der Express-Server gibt das von der Express Engine von Angular Univeral erstellte HTML-Dokument an den Client zurück
  6. Der Client empfängt die HTML und gibt sie wieder. Dem Benutzer wird eine vollständig gebildete Webseite angezeigt.
  7. Der Client fordert alle JavaScript-Bundles vom Server an. Nach dem Empfang führt der Client das JavaScript im Bundle aus.
    1. Es "hydrate" den HTML-Code, der in jedem clientseitigen JavaScript hinzugefügt wird, wie Ereignis-Listener.
    2. Angular übernimmt die serialisierten Daten automatisch von der Seite und injiziert sie in den JavaScript-Code, damit sie für die Komponenten verfügbar sind
  8. Wenn das HTML-Dokument ein Stylesheet enthält, fordert der Client das Stylesheet an.

Die Angular CLI unterstützt das Hinzufügen einer serverseitigen Rendering-Unterstützung zu einer vorhandenen Angular-Anwendung. Weitere Einzelheiten finden Sie unter https://angular.io/guide/universal.

Serverseitiger Express-Server

Die Serveranwendung verwendet einen Express-Server, um die Anforderung zu empfangen und an die Express Engine von Angular Univeral weiterzuleiten.

Die Express-Serverdatei befindet sich auf server.js. Diese Datei wird von der Angular CLI erstellt, wenn die Unterstützung für serverseitiges Rendering hinzugefügt wird.

Angular Components

Angulare Komponenten werden in TypeScript geschrieben und definieren eine Vorlage, die die Ansicht definiert. Diese Vorlagen enthalten allgemeine HTML-, Angular-Anweisungen und Binding-Markup, mit denen Angular die HTML vor der Wiedergabe anpassen kann.

Die Blog-Anwendung unterteilt jede Seite in eine Reihe kleinerer Komponenten.

Die nächsten Abschnitte bieten einen Überblick darüber, wie Angular unsere Anwendung in jeder unserer Komponenten wiedergibt:

App-Modul

Das App-Modul in src/app/app.module.ts. Die Anwendung wird mit der App-Komponente gebootet.

Diese Datei definiert die verschiedenen Routen für unsere Anwendung. Auf unserer Website möchten wir drei Routen anbieten:

Beachten Sie, dass sowohl die Themenseite als auch die Artikelseite ein Argument verwenden, das von Oracle Content Management in der URL bereitgestellt wird.

Die Homepage, die Themenseite und die Weiterleitungen der Artikelseite definieren die Resolver, mit denen alle für die Route erforderlichen Daten abgerufen werden, bevor die Komponenten der Route erstellt werden.

const appRoutes: Routes = [
      // home page - list of Topics
      {
        path: 'topics',
        component: TopicsListComponent,
        resolve: { routeData: TopicsListDataResolver }
      },
      // list of articles for a specific Topic
      {
        path: 'articles/:topicId',
        component: ArticlesListComponent,
        resolve: { routeData: ArticlesListDataResolver }
      },
      // details for a specific Article
      {
        path: 'article/:articleId',
        component: ArticleDetailsComponent,
        resolve: { routeData: ArticleDetailsDataResolver }
      },
      // no path specified, go to home
      {
        path: '',  redirectTo: '/topics', pathMatch: 'full'
      },
      // path not found
      { path: '**', component: PageNotFoundComponent },
    ];

Dieses App-Modul ist der Einstiegspunkt, wenn die Anwendung auf der Clientseite wiedergegeben wird.

Root-Modul für serverseitiges Rendering

Der wichtigste Einstiegspunkt für diese Angular-Anwendung ist bei der Wiedergabe der Anwendung auf dem Server das App-Servermodul in src/app/app.server.module.ts.

Dieses Modul importiert das App-Modul in src/app/app.server.module.ts, zusammen mit Angulars ServerModule. Die serverseitige Anwendung bootstrapt dieselbe App-Komponente wie der Client und verwendet alle gleichen Komponenten.

Die Angular CLI erstellt die Servermoduldatei, wenn die serverseitige Wiedergabeunterstützung hinzugefügt wird.

Themenlistendaten-Resolver

Der Daten-Resolver in der Themenliste " src/resolver/topics-list-data.resolver.ts" behandelt das Abrufen der auf der Homepage anzuzeigenden Daten.

Wenn der Client hydriert, werden diese Daten aus transferState abgerufen, das beim serverseitigen Rendering aufgefüllt und in das an den Client zurückgegebene HTML-Dokument serialisiert wurde.

Während des serverseitigen Renderings oder des clientseitigen Renderings, wenn die clientseitige Navigation erfolgt ist, enthält transferState die Daten nicht. Die Daten werden vom Oracle Content Management-Server mithilfe des Content SDK abgerufen, indem die Methode getTopicsListPageData() von src/scripts/services.js aufgerufen wird.

Artikellistendaten-Resolver

Der Artikel listet Daten-Resolver in src/resolver/articles-list-data.resolver.ts auf, verarbeitet das Abrufen der auf der Themenseite anzuzeigenden Daten.

Wenn der Client hydriert, werden diese Daten aus transferState abgerufen, das beim serverseitigen Rendering aufgefüllt und in das an den Client zurückgegebene HTML-Dokument serialisiert wurde.

Während des serverseitigen Renderings oder des clientseitigen Renderings, wenn die clientseitige Navigation erfolgt ist, enthält transferState die Daten nicht. Die Daten werden vom Oracle Content Management-Server mithilfe des Content SDK abgerufen, indem die Methode fetchTopicArticles() von src/scripts/services.js aufgerufen wird.

Artikeldetails - Datenresolver

Der in src/resolver/article-details-data.resolver.ts enthaltene Daten-Resolver verarbeitet das Abrufen der auf der Artikelseite anzuzeigenden Daten.

Wenn der Client hydriert, werden diese Daten aus transferState abgerufen, das beim serverseitigen Rendering aufgefüllt und in das an den Client zurückgegebene HTML-Dokument serialisiert wurde.

Während des serverseitigen Renderings oder des clientseitigen Renderings, wenn die clientseitige Navigation erfolgt ist, enthält transferState die Daten nicht. Die Daten werden vom Oracle Content Management-Server mithilfe des Content SDK abgerufen, indem die Methode fetchArticleDetails() von src/scripts/services.js aufgerufen wird.

App-Komponente

Die App-Komponente in src/app/app.component.ts definiert die Root-Ansicht.

Diese Komponente enthält die Router-Link-Tags. Angular tauscht Komponenten auf und von der Seite innerhalb dieser Tags auf Basis der aktuellen Route aus.

TopicsList-Komponente

Die Homepage besteht aus einer Liste mit einzelnen Themen. Sie wird von der Komponente TopicsList in src/app/topics-list/topics-list.component.ts wiedergegeben.

In ngOnInit ruft die Komponente die Daten aus der aktiven Route ab, die von dem Datenauflöser der Themenliste aufgefüllt wurde.

ngOnInit() {
      const data = this.route.snapshot.data.routeData;
      . . .
    }

Wenn die Komponente wiedergibt, werden alle Daten aus den zugehörigen Elementvariablen abgerufen.

Das Markup für die Komponente TopicsList befindet sich unter src/app/topics-list/topics-list.component.html.

TopicListItem-Komponente

Die Komponente TopicsList verwendet die Komponente TopicsListItem, um das einzelne Thema in der Liste anzuzeigen.

Sie befindet sich in src/app/topic-list-item.component.ts und empfängt alle zugehörigen Daten als Eigenschaften. Es werden keine zusätzlichen Daten vom Server abgerufen.

Das Markup für die Komponente TopicsListItem befindet sich in src/app/topic-list-item.component.html.

ArticlesList-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 ArticlesList in src/app/articles-list.component.ts wiedergegeben.

In ngOnInit können Sie sehen, dass die Komponente die Daten aus der aktiven Route abruft, die vom Resolver der Artikelliste aufgefüllt wurde.

ngOnInit() {
      const data = this.route.snapshot.data.routeData;
      . . .
    }

Wenn die Komponente wiedergibt, ruft sie alle Daten aus ihren Elementvariablen ab.

Das Markup für die Komponente ArticlesList befindet sich in src/app/articles-list.component.html.

ArticleListItem-Komponente

Die Komponente ArticlesList verwendet die Komponente ArticleListItem, um den einzelnen Artikel in der Liste anzuzeigen.

Diese Komponente befindet sich in src/app/article-list-item.component.ts und empfängt alle ihre Daten als Eigenschaften. Es werden keine zusätzlichen Daten vom Server abgerufen.

Das Markup für die Komponente ArticleListItem befindet sich in src/app/article-list-item.component.html.

ArticleDetails-Komponente

Auf der Seite "Artikel" werden Details des Artikels angezeigt, dessen ID an die URL übergeben wird. Sie wird von der Komponente ArticleDetails in src/app/article-details.component.ts wiedergegeben.

In ngOnInit können Sie sehen, dass die Komponente die Daten aus der aktiven Route abruft, die vom Resolver der Artikelliste aufgefüllt wurde.

ngOnInit() {
      // get the values from the routed URL
      this.articleId = this.route.snapshot.params[PAGE_PARAM_TOPIC_ARTICLE_ID];
      this.topicId = this.route.snapshot.queryParams[PAGE_PARAM_TOPIC_ID];
      this.topicName = this.route.snapshot.queryParams[PAGE_PARAM_TOPIC_NAME];
    
      const data = this.route.snapshot.data.routeData;
      . . .
    }

Wenn die Komponente wiedergibt, werden alle Daten aus den zugehörigen Elementvariablen abgerufen.

Das Markup für die Komponente ArticleDetails befindet sich in src/app/article-details.component.html.

Aufgabe 3: Anwendung auf das Deployment vorbereiten

Nachdem wir unsere Angular-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:

  1. Lokalen Entwicklungsserver hochfahren
  2. 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:4200, um Ihre Site in Aktion anzuzeigen.

Verwenden von Skripten zum Erstellen und Ausführen der Anwendung in Entwicklung und Produktion

Zur Produktion wird das Build-Skript verwendet, um den Client- und Servercode zu erstellen.

npm run build

Dieses Skript führt zuerst den Client-Build aus und führt dann den Server-Build aus. Der integrierte dist/server und dist/browser müssen auf dem Serverrechner bereitgestellt werden, bevor Sie die Serveranwendung mit dem folgenden Befehl starten:

npm run start

Schlussfolgerung

In diesem Tutorial haben wir eine Blogsite in Angular erstellt, die auf GitHub zu finden ist. Diese Site verwendet Oracle Content Management als Headless-CMS. Nachdem wir Oracle Content Management mit einem Kanal veröffentlichter Inhalte für das Tutorial der Blogsite eingerichtet und konfiguriert haben, wurde die Angular-Site installiert und ausgeführt, um die erforderlichen Inhalte abzurufen und die Site zu erstellen.

Weitere Informationen zu Angular finden Sie auf der Angular-Website.

Machen Sie sich mit wichtigen Oracle Content Management-Konzepten in der Dokumentation vertraut.

Weitere Beispiele finden Sie auf der Seite Oracle Content Management-Beispiele im Oracle Help Center.