Next.js應用程式
[AEM Headlessas a Cloud Service]{class="badge informative"}
範例應用程式是探索Adobe Experience Manager (AEM)無周邊功能的絕佳方式。 此Next.js應用程式示範了如何使用AEM的GraphQL API透過持久查詢來查詢內容。 適用於JavaScript的AEM Headless Client是用來執行GraphQL持續性查詢,以支援此應用程式。
使用AEM Headless的
在GitHub🔗上檢視原始程式碼
先決條件 prerequisites
下列工具應在本機安裝:
AEM需求
Next.js應用程式可與下列AEM部署選項搭配使用。 所有部署都需要在AEM as a Cloud Service環境中安裝WKND Shared v3.0.0+或WKND Site v3.0.0+。
此範例Next.js應用程式設計來連線至 AEM Publish 服務。
AEM作者需求
Next.js的設計可連線至 AEM Publish 服務,並存取未受保護的內容。 Next.js可設定為透過下述的.env
屬性連線到AEM Author。 由AEM Author提供的影像需要驗證,因此存取Next.js應用程式的使用者也必須登入AEM Author。
使用方式
-
複製
adobe/aem-guides-wknd-graphql
存放庫:code language-shell $ git clone git@github.com:adobe/aem-guides-wknd-graphql.git
-
編輯
aem-guides-wknd-graphql/next-js/.env.local
檔案並將NEXT_PUBLIC_AEM_HOST
設定為AEM服務。code language-plain # AEM service NEXT_PUBLIC_AEM_HOST=https://publish-p123-e456.adobeaemcloud.com/ ...
如果連線到AEM Author服務,則必須提供驗證,因為根據預設,AEM Author服務是安全的。
若要使用本機AEM帳戶集
AEM_AUTH_METHOD=basic
,並在AEM_AUTH_USER
和AEM_AUTH_PASSWORD
屬性中提供使用者名稱和密碼。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
若要使用AEM as a Cloud Service本機開發權杖,請設定
AEM_AUTH_METHOD=dev-token
,並在AEM_AUTH_DEV_TOKEN
屬性中提供完整的開發權杖值。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
-
編輯
aem-guides-wknd-graphql/next-js/.env.local
檔案並驗證NEXT_PUBLIC_AEM_GRAPHQL_ENDPOINT
已設定為適當的AEM GraphQL端點。使用WKND共用或WKND網站時,請使用
wknd-shared
GraphQL API端點。code language-plain ... NEXT_PUBLIC_AEM_GRAPHQL_ENDPOINT=wknd-shared ...
-
開啟命令提示字元,並使用下列命令啟動Next.js應用程式:
code language-shell $ cd aem-guides-wknd-graphql/next-js $ npm install $ npm run dev
-
新的瀏覽器視窗會在http://localhost:3000開啟Next.js應用程式
-
Next.js應用程式會顯示冒險清單。 選取冒險會在新頁面中開啟其詳細資訊。
程式碼
以下摘要說明如何建立Next.js應用程式、其如何連線至AEM Headless以使用GraphQL持續查詢擷取內容,以及資料如何呈現。 您可以在GitHub上找到完整程式碼。
持久查詢
依照AEM Headless最佳實務,Next.js應用程式會使用AEM GraphQL持續查詢來查詢冒險資料。 應用程式使用兩個持續查詢:
wknd/adventures-all
持續查詢,這會傳回AEM中所有具有刪節屬性集的冒險。 此持續查詢會驅動初始檢視的冒險清單。
# 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
}
}
}
}
}
wknd/adventure-by-slug
持續查詢,會傳回slug
的單一冒險(唯一識別冒險的自訂屬性)和完整屬性集。 此持續性查詢可為冒險詳細資料檢視提供支援。
# 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
}
}
}
}
執行GraphQL持久查詢
AEM的持久查詢會透過HTTPGET執行,因此JavaScript的AEM Headless使用者端是用來對AEM執行持久的GraphQL查詢,並將冒險內容載入應用程式。
每個持續查詢在src/lib//aem-headless-client.js
中都有對應的函式,它會呼叫AEM GraphQL端點,並傳回冒險資料。
每個函式又會叫用aemHeadlessClient.runPersistedQuery(...)
,執行持續的GraphQL查詢。
// 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) { ... }
...
頁面
Next.js應用程式使用兩個頁面來呈現冒險資料。
-
src/pages/index.js
使用Next.js的getServerSideProps()來呼叫
getAllAdventures()
,並將每個冒險活動顯示為卡片。使用
getServerSiteProps()
可讓伺服器端轉譯此Next.js頁面。 -
src/pages/adventures/[...slug].js
顯示單一冒險詳細資料的Next.js動態路由。 此動態路由會使用Next.js的getStaticProps(),透過
getAdventureBySlug(slug, queryVariables)
的呼叫,使用透過adventures/index.js
頁面上的冒險選項傳入的slug
引數預先擷取每個冒險的資料,並使用queryVariables
來控制影像格式、寬度和品質。動態路由可以使用Next.js的getStaticPaths(),並根據GraphQL查詢
getAdventurePaths()
傳回的完整冒險清單填入所有可能的路由排列,預先擷取所有冒險的詳細資料使用
getStaticPaths()
和getStaticProps(..)
允許靜態網站產生這些Next.js頁面。
部署設定
Next.js應用程式,尤其是在伺服器端轉譯(SSR)和伺服器端產生(SSG)的內容中,不需要進階安全性設定,例如跨原始資源共用(CORS)。
不過,如果Next.js確實從使用者端內容對AEM發出HTTP請求,則可能需要AEM中的安全性設定。 如需詳細資訊,請檢閱AEM Headless單頁應用程式部署教學課程。