Next.js-App

[AEM Headless as a Cloud Service]{class="badge informative"}

Beispielanwendungen eignen sich hervorragend, um die Headless-Funktionen von Adobe Experience Manager (AEM) zu erkunden. Diese Next.js-App zeigt, wie Inhalte mit den AEM GraphQL-APIs unter Verwendung persistierter Abfragen abgefragt werden können. Der AEM Headless-Client für JavaScript wird verwendet, um die von GraphQL gespeicherten Abfragen auszuführen, die die App antreiben.

Next.js-App mit AEM Headless

Sie finden den Quell-Code auf GitHub.

Voraussetzungen prerequisites

Folgende Tools sollten lokal installiert werden:

AEM-Anforderungen

Die Next.js-App funktioniert mit den folgenden AEM-Bereitstellungsoptionen. Alle Bereitstellungen erfordern, dass WKND Shared v3.0.0+ oder die WKND-Site v3.0.0+ in der AEM as a Cloud Service-Umgebung installiert werden.

Diese Next.js-Beispiel-App ist für die Verbindung mit dem AEM Publish-Service konzipiert.

AEM Author-Anforderungen

Next.js wurde entwickelt, um eine Verbindung zum AEM Publish-Service herzustellen und auf ungeschützte Inhalte zuzugreifen. Next.js kann so konfiguriert werden, dass eine Verbindung zu AEM Author über die unten beschriebenen .env-Eigenschaften hergestellt wird. Bilder, die von AEM Author bereitgestellt werden, erfordern eine Authentifizierung. Daher muss der Benutzende, der auf die Next.js-App zugreift, auch bei AEM Author angemeldet sein.

Informationen zur Verwendung

  1. Klonen Sie das Repository adobe/aem-guides-wknd-graphql:

    code language-shell
    $ git clone git@github.com:adobe/aem-guides-wknd-graphql.git
    
  2. Bearbeiten Sie die Datei aem-guides-wknd-graphql/next-js/.env.local und setzen Sie NEXT_PUBLIC_AEM_HOST auf den AEM-Service.

    code language-plain
    # AEM service
    NEXT_PUBLIC_AEM_HOST=https://publish-p123-e456.adobeaemcloud.com/
    ...
    

    Wenn eine Verbindung zum AEM-Autoren-Service hergestellt wird, muss die Authentifizierung durchgeführt werden, da der AEM-Autoren-Service standardmäßig sicher ist.

    Um ein lokales AEM-Konto zu verwenden, setzen Sie AEM_AUTH_METHOD=basic und geben Sie den Benutzernamen und das Passwort in den Eigenschaften AEM_AUTH_USER und AEM_AUTH_PASSWORD an.

    code language-plain
    ...
    # The variables are not prefixed with NEXT_PUBLIC so they are only available server-side
    AEM_AUTH_METHOD=basic
    AEM_AUTH_USER=aem-user-account
    AEM_AUTH_PASSWORD=password-for-the-aem-user-account
    

    Um ein lokales Entwicklungstoken von AEM as a Cloud Service zu verwenden, setzen Sie AEM_AUTH_METHOD=dev-token und geben Sie den vollständigen Wert des Dev-Token in der Eigenschaft AEM_AUTH_DEV_TOKEN an.

    code language-plain
    ...
    # The variables are not prefixed with NEXT_PUBLIC so they are only available server-side
    AEM_AUTH_METHOD=dev-token
    AEM_AUTH_DEV_TOKEN=my-dev-token
    
  3. Bearbeiten Sie die Datei aem-guides-wknd-graphql/next-js/.env.local und überprüfen Sie, ob NEXT_PUBLIC_AEM_GRAPHQL_ENDPOINT auf den entsprechenden AEM GraphQL-Endpunkt eingestellt ist.

    Wenn Sie WKND Shared oder WKND Site verwenden, benutzen Sie den wknd-shared GraphQL-API-Endpunkt.

    code language-plain
    ...
    NEXT_PUBLIC_AEM_GRAPHQL_ENDPOINT=wknd-shared
    ...
    
  4. Öffnen Sie eine Eingabeaufforderung und starten Sie die Next.js-App mit den folgenden Befehlen:

    code language-shell
    $ cd aem-guides-wknd-graphql/next-js
    $ npm install
    $ npm run dev
    
  5. Ein neues Browser-Fenster öffnet die Next.js-App unter http://localhost:3000

  6. Die Next.js-App zeigt eine Liste von Adventures an. Die Auswahl eines Adventures öffnet seine Details auf einer neuen Seite.

Der Code

Nachstehend finden Sie eine Zusammenfassung dazu, wie die Next.js-App erstellt wurde, wie sie eine Verbindung zu AEM Headless herstellt, um mithilfe von durch GraphQL persistierten Abfragen Inhalte abzurufen und wie diese Daten dargestellt werden. Den vollständigen Code finden Sie auf GitHub.

Persistierte Abfragen

Gemäß den Best Practices von AEM Headless verwendet die Next.js-App AEM GraphQL persistierte Abfragen, um Adventure-Daten abzufragen. Die App verwendet zwei persistierte Abfragen:

  • wknd/adventures-all persistierte Abfrage, die alle Adventures in AEM mit einer gekürzten Reihe von Eigenschaften zurückgibt. Diese persistierte Abfrage bestimmt die Erlebnisliste der ersten Ansicht.
# Retrieves a list of all Adventures
#
# Optional query variables:
# - { "offset": 10 }
# - { "limit": 5 }
# - {
#    "imageFormat": "JPG",
#    "imageWidth": 1600,
#    "imageQuality": 90
#   }
query ($offset: Int, $limit: Int, $sort: String, $imageFormat: AssetTransformFormat=JPG, $imageWidth: Int=1200, $imageQuality: Int=80) {
  adventureList(
    offset: $offset
    limit: $limit
    sort: $sort
    _assetTransform: {
      format: $imageFormat
      width: $imageWidth
      quality: $imageQuality
      preferWebp: true
  }) {
    items {
      _path
      slug
      title
      activity
      price
      tripLength
      primaryImage {
        ... on ImageRef {
          _path
          _dynamicUrl
        }
      }
    }
  }
}
  • Die persistierte Abfrage wknd/adventure-by-slug gibt ein einzelnes Adventure durch slug (eine benutzerdefinierte Eigenschaft, die ein Adventure eindeutig identifiziert) mit einer vollständigen Reihe von Eigenschaften zurück. Diese persistierte Abfrage ermöglicht Detailansichten des Adventures.
# Retrieves an Adventure Fragment based on it's unique slug.
#
# Required query variables:
# - {"slug": "bali-surf-camp"}
#
# Optional query variables:
# - {
#     "imageFormat": "JPG",
#     "imageSeoName": "my-adventure",
#     "imageWidth": 1600,
#     "imageQuality": 90
#   }
#
# This query returns an adventure list but since the the slug property is set to be unique in the Content Fragment Model, only a single Content Fragment is expected.

query ($slug: String!, $imageFormat:AssetTransformFormat=JPG, $imageSeoName: String, $imageWidth: Int=1200, $imageQuality: Int=80) {
  adventureList(
    filter: {slug: {_expressions: [{value: $slug}]}}
    _assetTransform: {
      format: $imageFormat
      seoName: $imageSeoName
      width: $imageWidth
      quality: $imageQuality
      preferWebp: true
  }) {
    items {
      _path
      title
      slug
      activity
      adventureType
      price
      tripLength
      groupSize
      difficulty
      price
      primaryImage {
        ... on ImageRef {
          _path
          _dynamicUrl
        }
      }
      description {
        json
        plaintext
        html
      }
      itinerary {
        json
        plaintext
        html
      }
    }
    _references {
      ... on AdventureModel {
        _path
        slug
        title
        price
        __typename
      }
    }
  }
}

Durchführen einer GraphQL-persistierten Abfrage

Die persistierten Abfragen von AEM werden über HTTP GET ausgeführt und daher wird der AEM Headless-Client für JavaScript verwendet, um die persistierten GraphQL-Abfragen gegen AEM auszuführen und den Adventure-Inhalt in die App zu laden.

Jede persistierte Abfrage verfügt über eine entsprechende Funktion in src/lib//aem-headless-client.js, die den AEM GraphQL-Endpunkt aufruft und die Adventure-Daten zurückgibt.

Jede Funktion ruft wiederum die aemHeadlessClient.runPersistedQuery(...) auf, um die persistierte GraphQL-Abfrage auszuführen.

// src/lib/aem-headless-client.js

...
/**
 * Invokes the 'adventures-all` persisted query using the parameterizable namespace.
 *
 * @returns a GraphQL response of all adventures.
 */
async getAllAdventures() {
  const queryAdventuresAll = process.env.NEXT_PUBLIC_AEM_GRAPHQL_ENDPOINT + '/adventures-all';

  try {
    return await this.aemHeadlessClient.runPersistedQuery(queryAdventuresAll);
  } catch(e) {
    console.error(e)
  }
}

// And so on, and so forth ...

async getAdventureSlugs(queryVariables) { ... }

async getAdventuresBySlug(slug, queryVariables) { ... }
...

Seiten

Die Next.js-App verwendet zwei Seiten, um die Adventure-Daten darzustellen.

  • src/pages/index.js

    Verwendet getServerSideProps() von Next.js, um getAllAdventures() aufzurufen und zeigt jedes Adventure als Karte an.

    Die Verwendung von getServerSiteProps() ermöglicht das serverseitige Rendering dieser Next.js-Seite.

  • src/pages/adventures/[...slug].js

    Eine Dynamische Route von Next.js, die die Details eines einzelnen Adventures anzeigt. Diese dynamische Route ruft die Daten jedes Abenteuers mithilfe von getStaticProps() in Next.js über einen Aufruf von getAdventureBySlug(slug, queryVariables) mithilfe des slug-Parameters, der über die Abenteuerauswahl auf den Seiten adventures/index.js und queryVariables weitergegeben wurde, im Voraus ab, um Bildformat, -breite und -qualität zu regeln.

    Die dynamische Route ist in der Lage, die Details für alle Adventures im Voraus abzurufen, indem sie getStaticPaths() von Next.js verwendet und alle möglichen Routen-Permutationen auf der Grundlage der vollständigen Liste der Adventures, die von der GraphQL-Abfrage getAdventurePaths() zurückgegeben werden, auffüllt.

    Die Verwendung von getStaticPaths() und getStaticProps(..) ermöglichte die statische Site-Generierung dieser Next.js-Seiten.

Bereitstellungskonfiguration

Next.js-Apps, insbesondere im Zusammenhang mit Server-seitigem Rendering (SSR) und Server-seitiger Generierung (SSG), erfordern keine erweiterten Sicherheitskonfigurationen wie Cross-Origin Resource Sharing (CORS).

Wenn jedoch Next.js im Client-Kontext HTTP-Anfragen an AEM sendet, sind möglicherweise Sicherheitskonfigurationen in AEM erforderlich. Überprüfen Sie das Tutorial zur Bereitstellung von AEM Headless-Einzelseiten-App für weitere Details.

recommendation-more-help
e25b6834-e87f-4ff3-ba56-4cd16cdfdec4