使用 Headless Oracle Content Management 在 Next.js 中建立影像庫
簡介
Next.js 是一個開放原始碼 React 前端開發 Web 架構,可啟用伺服器端呈現及產生 React 式 Web 應用程式的靜態網站等功能。
此教學課程將介紹使用 Next.js 建立影像檢視器的基本步驟,並以 Oracle Content Management 作為內容管理系統及其 Content SDK。您將會見到如何使用分類來分類內容,以及如何將數位資產的不同轉譯用於各種使用案例。此 Next.js 範例位於 GitHub 上。
此教學課程包含三個工作:
必要條件
繼續本教學課程之前,建議您先閱讀下列資訊:
若要遵循此教學課程,您需要:
- Oracle Content Management 訂閱
- 具備內容管理員角色的 Oracle Content Management 帳戶
- 節點版本 10 或更新版本的 Windows 或 Mac 電腦
我們正在建立什麼
我們的圖片庫將由一間咖啡咖啡店提供的數個食物與飲料影像頁所組成。

為了看看我們正在建立的內容,以下是我們教學課程的結束狀態,這是此影像庫網站的即時版本:
https://headless.mycontentdemo.com/samples/oce-nextjs-gallery-sample
類別是分類的子項節點,可以組織成階層。對於我們的影像詳細目錄展示、不論組織為何、我們都要顯示所有可用的分類。為了達成此目的,我們必須先尋找可用的分類,使用 Content SDK 的 getTaxonomies() 方法。
注意:getTaxonomies 的實行使用 REST API 資源 GET /published/api/v1.1/taxonomies。
接著,我們需要取得每個分類的類別集。這是使用 Content SDK 的 queryTaxonomyCategories() 方法來完成的。
注意:queryTaxonomyCategories 的實行使用 REST API GET /published/api/v1.1/taxonomies/{id}/categories。
若要建立類別 (例如 Bagels) 的預覽,我們必須取得影像數目和前四個影像的 URL 計數。

我們在類別中尋找已發布資產的要求透過查詢字串指定類別條件,如下所示:
"(taxonomies.categories.nodes.id eq 892CD6BC4F654249A00CB7942EE8C773)"
為了最佳化影像載入,我們將使用名為「縮圖」的影像轉譯。請參閱 scripts/services.js 中的 retrieveThumbnailURL(),瞭解檢查每個影像一組可用轉譯的程式碼。
注意:除了發布想要檢視的數位資產之外,您還需要將分類發布至通道。
若要繼續,您必須要有 Oracle Content Management 的作用中訂閱,並且必須以「內容管理員」角色登入。
工作 1:準備 Oracle Content Management
此教學課程是以您已建立資產儲存區域的假設為基礎,且目前的內容模型是空的 (亦即未建立任何內容類型)。
如果您還沒有 Oracle Content Management 例項,請參閱快速入門以瞭解如何註冊 Oracle Cloud、佈建 Oracle Content Management 例項,以及將 Oracle Content Management 設定為無頭 (headless) CMS。
在此教學課程中,您需要以下列兩種方式之一來建立內容模型。有一個可下載的資產套件可將內容類型和關聯的內容填入您的空白儲存區域,或者您也可以建立自己的內容模型和內容。
若要準備 Oracle Content Management:
建立通道和資產儲存區域
您必須先在 Oracle Content Management 中建立通道和資產儲存區域,才能夠發布內容。
在 Oracle Content Management 中建立通道和資產儲存區域:
以管理員身分登入 Oracle Content Management Web 介面。
從左邊導覽功能表中選擇內容,然後從頁面標頭的選取清單中選擇發布通道。

在右上角,按一下建立以建立新的通道。為此教學課程目的命名通道’OCEImageGalleryChannel’,並將存取權保持公開。按一下儲存以建立管道。

從左邊導覽功能表中選擇內容,然後從頁面標頭的選擇清單中選擇儲存區域。

在右上角,按一下建立以建立新的資產儲存區域。為此教學課程目的命名資產儲存區域‘OCEImageGalleryRepository’。

在發布通道欄位中,選取 OCEImageGalleryChannel 以指示 Oracle Content Management 中可將 OCEImageGalleryRepository 儲存區域中的內容發布至 OCEImageGalleryChannel 通道。完成後,請按一下儲存。

匯入 Oracle Content Management 範例資產套件
您可以下載預先設定的 Oracle Content Management 範例資產套件,其中包含此教學課程的所有必要內容類型和資產。
您可以從 Oracle Content Management Sample Asset Pack 上傳我們在此教學課程中使用的內容複本。這可讓您實驗內容類型並修改內容。您可以下載 OCESamplesAssetPack.zip 資產套件存檔,然後將它解壓縮至您選擇的目錄:
從 Oracle Content Management 下載頁面下載 Oracle Content Management 範例資產套件 (OCESamplesAssetPack.zip)。將下載的壓縮檔解壓縮至您電腦上的位置。解壓縮之後,此位置會包含一個名為 OCEImageGallery_data.zip 的檔案。
以管理員身分登入 Oracle Content Management Web 介面。
從左邊導覽功能表中選擇內容,然後從頁面標頭的選擇清單中選擇儲存區域。現在選取 OCEImageGalleryRepository,然後按一下頂端動作列中的匯入內容按鈕。

將 OCEImageGallery_data.zip 從本機電腦上傳至 Documents 資料夾。

上傳後,請選取 OCEImageGallery_data.zip,然後按一下確定,將內容匯入您的物件儲存區域中。

順利匯入內容之後,請瀏覽至資產頁面並開啟 OCEImageGalleryRepository 儲存區域。您將會見到所有相關影像和內容項目現在都已新增至物件儲存區域。

按一下左上方的全選,然後按一下發布,將所有匯入的資產新增至您先前建立的發布通道 OCEImageGalleryChannel。

發布之前,您必須先驗證所有資產。請先將 OCEImageGalleryChannel 新增為選取的管道,然後按一下驗證按鈕。

驗證資產之後,您可以按一下右上角的發布按鈕,將所有資產發布至選取的通道。

完成之後,您就會在已發布所有資產的資產頁面中見到該頁面。(您可以透過資產名稱上方的圖示來辨識。)

匯入 Oracle Content Management 範例資產套件之後,您可以開始在 Next.js 中建立影像庫。
上傳您自己的影像資產
在此教學課程中,我們使用名為‘OCEImageGalleryRepository’的資產儲存區域來建立我們圖庫網站的首頁。此首頁包含標題「影像庫」以及內部有影像資產的影像集合相簿。

新增影像資產至儲藏庫資產儲存區域:
登入 Oracle Content Management Web 介面。
按一下左側導覽功能表中的資產。
開啟 OCEImageGalleryRepository 儲存區域。
按一下頁面右上角的新增,將影像資產新增至圖庫資產儲存區域。

從本機電腦上傳您自己的新資產,或選擇 Oracle Content Management 中已有的現有資產。
建立分類並將其連結至影像資產
您需要在 Oracle Content Management 中建立分類,然後將類別指派給儲存區域中的資產。
若要在 Oracle Content Management 中建立分類,請執行下列動作:
以管理員身分登入 Oracle Content Management Web 介面。
從左邊導覽功能表中選擇內容,然後從頁面標頭的選取清單中選擇分類。

在右上角,按一下建立以建立新分類。為此教學課程目的命名通路‘OCEImageGalleryTaxonomy’。

按一下建立。
現在新增類別以建置分類。按一下新增類別。

將上階分類料號命名為「食品」,並新增下列下階分類:
- 早餐
- Dessert
- 飲料
- 三明治
按一下畫面右上角的完成。

在分類頁面中,選取 OCEImageGalleryTaxonomy 分類並按一下動作列中的升級,即可將它提供給您的資產儲存區域使用。

接著,編輯 OCEImageGalleryRepository 儲存庫以啟用該儲存庫的 OCEImageGalleryTaxonomy 分類標準:
以管理員身分登入 Oracle Content Management Web 介面。
從左邊導覽功能表中選擇內容,然後從頁面標頭的選擇清單中選擇儲存區域。
選取並編輯 OCEImageGalleryRepository 儲存區域。
在分類欄位中,選取 OCEImageGalleryTaxonomy,以便將該分類的類別指派給 OCEImageGalleryRepository 儲存區域中的資產。

按一下儲存。
然後,將分類類別指派給 OCEImageGalleryRepository 儲存區域中的每個影像資產:
登入 Oracle Content Management Web 介面。
按一下左側導覽功能表中的資產。
開啟 OCEImageGalleryRepository 儲存區域。
選取一或多個影像資產,按一下動作列中的其他,然後從功能表中選擇類別。

在類別面板中,按一下新增類別。在搜尋列中搜尋類別名稱,或從分類階層結構中選取類別,然後按一下新增來指派選取的類別。您可以將多個類別指派給資產。

完成將分類指定給所有影像資產之後,請選取儲存區域中的所有資產,然後將它們發布至 OCEImageGalleryChannel 通道。
工作 2:在 Next.js 中建立圖庫
為了在 Next.js 應用程式中使用我們的 Oracle Content Management 內容,我們可以使用 Next.js 圖庫範例作為 GitHub 上的開放原始碼儲存區域。
注意:請記住,使用 Next.js 範例是選擇性的,我們會在此教學課程中使用它來快速入門。您也可以建置自己的 Next.js 應用程式。
在 Next.js 中建立影像圖庫:
複製範例儲存區域並安裝相依性
Next.js 部落格範例可作為 GitHub 的開放原始碼儲存區域。
您必須先將 GitHub 的範例複製到您的本機電腦,然後將您的目錄變更為儲存區域根目錄:
git clone https://github.com/oracle/oce-nextjs-gallery-sample.git
cd oce-nextjs-gallery-sample
現在,您的程式碼基礎需要下載應用程式的相依性。從根目錄執行下列命令:
npm install
設定 Next.js 應用程式
在此 Next.js 影像圖庫範例中,您需要設定一些資訊,讓您的 Oracle Content Management Content SDK (以及任何其他要求) 能夠以正確的通道記號為正確的執行處理 URL 和 API 版本設定目標。這些值用於命令檔/server-config-utils.js 中,以建立新的傳遞從屬端。
此應用程式使用.env.local 檔案,此檔案由 Next.js 讀取,並可供具有 process.env 的應用程式內的程式碼使用。
在文字編輯器中開啟.env.local 檔案。您會看到下列資訊:
# 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=e0b6421e73454818948de7b1eaddb091
變更每個索引鍵-值組以反映您的執行處理 URL、您要定位的 API 版本,以及與您發布通道關聯的通道權杖。此教學課程的管道是 OCEImageGalleryChannel。
使用 Oracle Content Management Content SDK
Oracle Content Management 提供一個 SDK 來協助尋找及使用您應用程式中的內容。SDK 會發佈為 NPM 模組,而專案則是在 GitHub 上代管。
請到這裡瞭解 SDK 的詳細資訊。
SDK 已經在 package.json 檔案中註冊為此專案的程式實際執行相依性。
使用 Content SDK 擷取內容
我們現在可以利用 Content SDK 擷取內容,以便在 Next.js 應用程式中呈現內容。
命令檔資料夾包含使用 Content SDK 從 Oracle Content Management 取得資料的程式碼。
命令檔/server-config-utils.js 檔案會匯入 Content SDK,然後使用.env.local 中指定的組態建立傳遞從屬端。
下列命令會匯入 SDK:
import { createDeliveryClient, createPreviewClient } from '@oracle/content-management-sdk';下列命令會建立傳遞從屬端:
return createDeliveryClient(serverconfig);scripts/services.js 檔案包含用來取得應用程式資料的所有程式碼。應用程式中的每個頁面元件都有一個主要功能,以取得該頁面的所有資料。
對於呈現影像,services.js 提供協助程式方法來擷取從資產轉譯建構之資產的來源集。
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;
}首頁資料
首頁需要數個資料呼叫,才能取得其所有資料:
- 首先,我們會為.env 中指定的通道載入分類。
- 對於每個分類,我們都會取得該分類中的所有類別。
- 對於每個類別,我們會取得該類別中的四個內容項目。
- 我們會針對每個項目取得其轉譯 URL。
開啟 src/scripts/services.js 並尋找 getHomePageData() 函數,此函數可用來取得首頁的所有資料。
export function getHomePageData() {
const deliveryClient = getClient();
// get the categories for all taxonomies then add all the category items to each category
return fetchAllTaxonomiesCategories(deliveryClient).then(
(initialCategories) => addItemsToCategories(deliveryClient, initialCategories).then(
(categories) => {
// pull out all of the items for all of the categories then
// append the computed renditionUrls to each item.
const allItems = categories.map((category) => category.items);
const items = flattenArray(allItems);
// for each item, retrieve the rendition urls and add it to the item
items.forEach((item) => {
item.renditionUrls = getSourceSet(item);
});
return { categories };
},
),
);
}getHomePageData() 會呼叫 fetchAllTaxonomiesCategories() 以取得所有分類中的所有類別。
export function fetchAllTaxonomiesCategories(client) {
return client
.getTaxonomies()
.then((topLevelItem) => {
const taxonomyIds = topLevelItem.items.map((taxonomy) => taxonomy.id);
const promises = [];
// loop over each taxonomy id
taxonomyIds.forEach((taxonomyId) => {
// add a promise to the total list of promises to get the categories
// for the specific taxonomy id
promises.push(
fetchCategoriesForTaxonomyId(client, taxonomyId)
.then((categoriesTopItem) => categoriesTopItem.items),
);
});
// execute all the promises returning a single dimension array of all
// of the categories for all of the taxonomies (note: no taxonomy information)
// is returned.
return Promise.all(promises)
.then((arrayOfCategoryArray) => flattenArray(arrayOfCategoryArray));
})
.catch((error) => logError('Fetching taxonomies failed', error));
}fetchAllTaxonomiesCategories() 會呼叫 fetchCategoriesForTaxonomyId() 以取得特定分類中的所有類別。
function fetchCategoriesForTaxonomyId(client, taxonomyId) {
return client
.queryTaxonomyCategories({
id: `${taxonomyId}`,
})
.then((topLevelItem) => topLevelItem)
.catch((error) => logError('Fetching categories for taxonomy failed', error));
}接著會呼叫 addItemsToCategories 函數,將四個類別項目新增至每個類別。
function addItemsToCategories(client, categories) {
const promises = [];
// loop over each category
categories.forEach((category) => {
// add a promise to the total list of promises to get the items
// for the specific category
promises.push(
fetchItemsForCategory(client, category.id, true).then(
(topLevelItem) => {
// add the item to the category before returning it
category.items = topLevelItem.items;
category.totalResults = topLevelItem.totalResults;
return {
...category,
};
},
),
);
});
// execute all the promises before returning the data
return Promise.all(promises).then((arrayOfItems) => flattenArray(arrayOfItems));
}最後,系統會先前呼叫 getSourceSet 來取得每個項目的轉譯 URL。
影像格線頁面資料
影像方格頁面會接收類別 ID,而且需要數個資料呼叫才能取得其所有資料:
- 取得指定類別的所有項目。
- 取得每個項目的轉譯 URL。
開啟 src/scripts/services.js 並尋找 getImageGridPageData() 函數,此函數可用來取得影像格線頁面的所有資料。
export function getImageGridPageData(categoryId) {
const client = getClient();
return fetchItemsForCategory(client, categoryId, false).then(
(topLevelItem) => {
const { totalResults } = topLevelItem;
// for each item, retrieve the rendition urls and add it to the item
topLevelItem.items.forEach((item) => {
item.renditionUrls = getSourceSet(item);
});
return {
totalResults,
items: topLevelItem.items,
};
},
);
}它會呼叫 fetchItemsForCategory,例如首頁,但不會限制,因此會傳回所有項目,而不只是四個。
現在我們有資料查詢,我們可以在我們的 Next.js 元件中轉譯回應。
Next.js 元件
Next.js是以React為基礎, React使用JSX (JavaScript的HTML語法副檔名)來呈現內容。雖然您可以撰寫純 JavaScript 來呈現 Oracle Content Management 的資料,但強烈建議您使用 JSX。
影像圖庫應用程式會將每個頁面細分為數個較小的元件,部分元件會同時用於首頁和影像格線頁面。
以下幾節概述 Next.js 在我們的每個元件中如何呈現應用程式:
頁面資料夾
在我們的網站中,我們想要提供兩個路由:
- 首頁,顯示影像類別清單
- 影像格線頁面,顯示指定分類識別碼的所有項目
頁面目錄 Next.js 中的任何頁面都會被視為應用程式的路由。
索引元件
首頁包含分類的類別清單,其中預覽該類別中的四個項目。它是由「索引」元件 (位於 pages/index.jsx) 所呈現。
元件會匯入 API 以從 services.js 檔案取得資料。
import { getHomePageData } from '../scripts/services';在組建期間呼叫的 getStaticProps() 中,元件會取得轉換首頁所需的所有資料。
export async function getStaticProps() {
const data = await getHomePageData();
return {
props: { data },
};
}儲藏庫元件
「圖庫」元件代表清單中的個別類別。它會顯示類別中四個項目的預覽。
它位於 src/components/Gallery.jsx,並接收其所有資料作為特性。它不會從伺服器取得任何其他資料。
ImageGridPage 元件
「影像網格頁面」元件會顯示類別中 ID 傳送至 URL 元件的項目。它是由 ArticleListPage 元件所呈現,位於 pages/category/[id] .jsx。
元件會匯入 API 以從 services.js 檔案取得資料。
import { fetchAllTaxonomiesCategories, getImageGridPageData } from '../../scripts/services';「影像格線頁面」的 URL 是動態 URL,其中包含類別 ID 和名稱作為路徑,範例 URL 路徑為
- /category/categoryId1-name1
- /category/categoryId2-name2
- /category/categoryId3-name3
Next.js 針對具有動態 URL 的頁面使用靜態網站產生時,會呼叫 getStaticPaths() 來取得該頁面的所有路徑。
export async function getStaticPaths() {
const categories = await fetchAllTaxonomiesCategories();
return {
paths: categories.map((category) => ({
params: { id: `${category.id}-${category.name}` },
})),
fallback: true,
};
}getStaticProps() 函數可用來取得「影像網格」頁面之單一執行處理的資料。類別 ID 和名稱是從傳送至方法的參數取得。接著會使用類別 ID 來取得此頁面所需的所有資料。
export async function getStaticProps(context) {
const { params } = context;
const { id } = params;
const arr = id.split('-');
const categoryName = arr[1];
const categoryId = arr[0];
const data = await getImageGridPageData(categoryId);
return {
props: {
data,
categoryName,
},
};
}作業 3:準備應用程式以進行建置
現在我們已建立 Next.js 部落格網站,我們必須在本機開發伺服器中看到此網站,以便為任何問題除錯,並在應用程式上線前預覽該應用程式。
使用兩個步驟準備應用程式以進行部署:
微調本機開發伺服器
您可以執行下列命令,在本機啟動開發伺服器。
npm run dev
然後,將您的瀏覽器開啟到http://localhost:3000,即可查看您的網站如何運作。
注意:這不會預先呈現頁面,為了預先呈現頁面,請參閱下一節。
使用命令檔在開發和生產環境中建置及執行應用程式
如果是實際環境執行,會使用組建命令檔以靜態方式產生網站。
npm run build
啟動命令檔是用來啟動提供靜態產生之頁面的 Node.js 伺服器。
npm run start
使用 Headless Oracle Content Management 在 Next.js 中建立影像庫
F49334-01
2021 年 10 月
Copyright © 2021, Oracle and/or its affiliates.
主要作者:Oracle Corporation