在 Next.js 中以 Headless Oracle Content Management 建立最小網站

簡介

Next.js 是一個開放原始碼 React 前端開發 Web 架構,可啟用伺服器端呈現及產生 React 式 Web 應用程式的靜態網站等功能。

為了在 Next.js 應用程式中使用 Oracle Content Management 內容,我們可以在 GitHub 上使用 Next.js 最小範例作為開放原始碼儲存區域。

在本教學課程中,我們將利用 Oracle Content Management 作為無頭 (headless) CMS,以及使用其軟體開發套件 (SDK) 在 JavaScript 中傳遞內容,在 Next.js 中建立簡單的最低網站。此 Next.js 範例位於 GitHub 上。

此教學課程包含三個工作:

  1. 準備 Oracle Content Management
  2. 在 Next.js 中建立最小網站
  3. 準備您的應用程式以進行部署

必要條件

繼續本教學課程之前,建議您先閱讀下列資訊:

若要遵循此教學課程,您需要:

我們正在建立什麼

透過 Next.js,您可以輕鬆地從 Oracle Content Management 儲存庫擷取影像和其他內容。

為了看看我們正在建置的內容,以下是我們教學課程的結束狀態,這是一種使用 Oracle Content Management 內容的基本 Next.js 最小網站:

https://headless.mycontentdemo.com/samples/oce-nextjs-minimal-sample

這是此教學課程結尾的首頁外觀:

此圖像顯示 Next.js 最小網站的登陸頁面。

此為此教學課程結尾的「與我們聯絡」頁面外觀:

此圖像顯示 Next.js 最少網站的「與我們聯絡」頁面。

若要繼續,您必須要有 Oracle Content Management 的作用中訂閱,並且必須以「內容管理員」角色登入。

工作 1:準備 Oracle Content Management

如果您還沒有 Oracle Content Management 例項,請參閱快速入門以瞭解如何註冊 Oracle Cloud、佈建 Oracle Content Management 例項,以及將 Oracle Content Management 設定為無頭 (headless) CMS。

在此教學課程中,您需要建立內容模型。有一個可下載的資產套件,可將內容類型和關聯的內容填入您的空白儲存區域。

若要準備 Oracle Content Management:

  1. 建立通道和資產儲存區域。
  2. 匯入 Oracle Content Management 範例資產套件

建立通道和資產儲存區域

您必須先在 Oracle Content Management 中建立通道和資產儲存區域,才能夠發布內容。

在 Oracle Content Management 中建立通道和資產儲存區域:

  1. 以管理員身分登入 Oracle Content Management Web 介面。

  2. 從左邊導覽功能表中選擇容,然後從頁面標頭的選取清單中選擇發布通道。

    此圖像顯示在「內容」頁面標頭的下拉式功能表中選取的發布通道選項。

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

    此圖像顯示發布通道定義面板,通道名稱欄位中有‘OCEMinimalChannel’。

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

    此圖像顯示在「內容」頁面標頭的下拉式功能表中選取的「儲存區域」選項。

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

    此圖像顯示儲存區域定義面板,儲存區域名稱欄位中有‘OCEMinimalRepository’。

  6. 發布通道欄位中,選取 OCEMinimalChannel 通道以指示 Oracle Content Management 能夠將 OCEMinimalRepository 儲存區域中的內容發布至 OCEMinimalChannel 通道。完成後,請按一下存。

    此圖像顯示儲存區域定義面板,「發布通道」欄位中有‘OCEMinimalChannel’。

建立內容模型

下一個工作是建立內容模型。您可以使用兩個方法中的任一個:

匯入 Oracle Content Management 範例資產套件

您可以下載預先設定的 Oracle Content Management 範例資產套件,其中包含此教學課程的所有必要內容類型和資產。如果您願意,您也可以建立自己的內容模型,而不是下載範例資產套件。

您可以從 Oracle Content Management Sample Asset Pack 上傳我們在此教學課程中使用的內容複本。這可讓您實驗內容類型並修改內容。若要匯入 Oracle Content Management Sample Asset Pack,您可以下載 OCESamplesAssetPack.zip 資產套件存檔,然後將它解壓縮至您選擇的目錄:

  1. 從 Oracle Content Management 載頁面下載 Oracle Content Management 範例資產套件 (OCESamplesAssetPack.zip)。將下載的壓縮檔解壓縮至您電腦上的位置。解壓縮之後,此位置將會包含一個名為 OCEMinimal_data.zip 的檔案。

  2. 以管理員身分登入 Oracle Content Management Web 介面。

  3. 從左邊導覽功能表中選擇容,然後從頁面標頭的選擇清單中選擇存區域。現在選取 OCEMinimalRepository,然後按一下頂端動作列中的匯入內容按鈕。

    此圖像顯示「儲存區域」頁面,其中已選取 OCEMinimalRepository 項目。

  4. 將 OCEMinimal_data.zip 從您的本機電腦上傳至 Documents 資料夾。

    此圖像顯示 OCEMinimal_data.zip 檔案的上傳確認畫面。

  5. 上傳之後,請選取 OCEMinimal_data.zip,然後按一下定,將內容匯入您的資產儲存區域中。

    此圖像顯示選取的 OCEMinimal_data.zip 檔案並啟用「確定」按鈕。

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

    此圖像顯示 OCEMinimalRepository 儲存區域,以及剛才匯入的所有資產。

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

    此圖像顯示 OCEMinimalRepository 儲存區域,其中已選取所有資產,並顯示動作列中的發布選項。

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

    此圖像顯示「驗證結果」頁面,其中 OCEMinimalChannel 通道已新增至通道欄位、要驗證的所有資產,以及啟用驗證按鈕。

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

    此圖像顯示「驗證結果」頁面,其中的 OCEMinimalChannel 通道已新增至通道欄位、所有已驗證的資產,以及啟用發布按鈕。

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

此圖像顯示「資產」頁面,其中所有資產都已發布。

匯入 Oracle Content Management 範例資產套件之後,您可以開始在 Next.js 中建立最小網站。

建立您自己的內容模型

您也可以建立自己的內容模型,而不是匯入 Oracle Content Management Sample Asset Pack

在此教學課程中,我們使用名為‘MinimalMain’的內容類型作為此範例的主要內容類型。此內容類型包含頁首和頁尾標誌,以及應包含在導覽上的頁面清單。

此圖像顯示「最小」範例的首頁。

建立內容模型的內容類型:

  1. 以管理員身分登入 Oracle Content Management Web 介面。
  2. 從左邊導覽功能表中選擇容,然後從頁面標頭的選取清單中選擇資產類型。
  3. 按一下右上角的建立
  4. 選擇此選項可建立內容類型 (非數位資產類型)。針對所有必要的內容類型重複此動作。

此圖像顯示 Oracle Content Management Web 介面中的「建立資產類型」對話方塊。

我們將建立三種內容類型,每種內容類型都有自己的欄位集:

第一個內容類型 (MinimalMain) 應具有下列欄位:

顯示名稱 欄位類型 必要 機器名稱
headerLogo 單一值媒體欄位 headerLogo
footerLogo 單一值媒體欄位 footerLogo
頁面 多個值參照欄位 pages -頁面

這是您的 MinimalMain 內容類型定義外觀:

此圖像顯示內容類型’MinimalMain' 的定義。其中包括下列資料欄位:headerLogo、footerLogo、頁面。

第二個內容類型 MinimalPage 應具有下列欄位:

顯示名稱 欄位類型 必要欄位 機器名稱
區段 多個值參照欄位 區段

這是您的 MinimalPage 內容類型外觀:

此圖像顯示內容類型’MinimalPage' 的定義。其中包括此資料欄位:區段。

第三和最終內容類型 MinimalSection 應具有下列欄位:

顯示名稱 欄位類型 必要欄位 機器名稱
類型 單一值文字欄位 X 類型
標題 單一值文字欄位 標題
body 單一值大型文字欄位 body
映像檔 單一值影像欄位 映像檔
動作 單一值內嵌內容欄位 動作

這是您的 MinimalSection 內容類型外觀:

此圖像顯示內容類型’MinimalSection' 的定義。其中包括下列資料欄位:類型、標題、內文、影像、動作。

建立內容類型之後,您可以將這些內容類型新增至先前建立的儲存區域 OCEMinimalRepository:

  1. 以管理員身分登入 Oracle Content Management Web 介面。
  2. 瀏覽至 OCEMinimalRepository
  3. 編輯儲存區域,然後在資產類型底下,指定所有三種新建立的內容類型。按一下「存」按鈕以儲存變更。

此圖像顯示 Oracle Content Management 中的「編輯儲存區域」頁面,其中有三個與 OCEMinimalRepository 儲存區域關聯的新建立內容類型。

將內容類型新增至儲存區域之後,您可以在資產頁面上開啟 OCEMinimalRepository 儲存區域,然後開始建立所有內容類型的內容項目。

此圖像顯示 Oracle Content Management Web 介面中「資產」頁面上的內容項目,左邊為集合、通道、語言、類型、選取的內容項目以及狀態選項。

作業 2:在 Next.js 中建立最小網站

為了在轉換的 Next.js 應用程式中使用 Oracle Content Management 內容,我們可以使用 Next.js 最小網站範例,此範例可作為 GitHub 上的開放原始碼儲存區域。

注意:請記住,使用 Next.js 範例是選擇性的,我們會在此教學課程中使用它來快速入門。您也可以建置自己的 Next.js 應用程式。

在 Next.js 中建立最小網站:

  1. 複製範例儲存區域並安裝相依性
  2. 設定 Next.js 應用程式
  3. 使用 Oracle Content Management Content SDK
  4. 使用 Content SDK 擷取內容

複製範例儲存區域並安裝相依性

Next.js 最小網站範例可作為 GitHub 上的開放原始碼儲存區域。

您必須先將 GitHub 的範例複製到您的本機電腦,然後將您的目錄變更為儲存區域根目錄:

git clone https://github.com/oracle/oce-nextjs-minimal-sample.git
    cd oce-nextjs-minimal-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=ba0efff9c021422cb134c2fd5daf6015

變更每個索引鍵-值組以反映您的執行處理 URL、您要定位的 API 版本,以及與您發布通道關聯的通道權杖。此教學課程的管道是 OCEMinimalChannel。

使用 Oracle Content Management Content SDK

Oracle Content Management 提供一個 SDK 來協助尋找及使用您應用程式中的內容。SDK 會發佈為 NPM 模組,而專案則是在 GitHub 上代管。

請到這裡瞭解 SDK 的詳細資訊。

SDK 已經在 package.json 檔案中註冊為此專案的程式實際執行相依性。

使用 Content SDK 擷取內容

我們現在可以利用 Content SDK 擷取內容,以便在 Next.js 應用程式中呈現內容。

Content SDK 使用 DeliveryClient 物件來指定端點。您可以使用該從屬端物件提出所有要求。

命令檔資料夾包含使用 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 檔案包含取得此 Next.js 最小應用程式資料的函數。

fetchOceMinimalMain() 方法會擷取網址幾乎最少的內容類型 MinimalMain。

export async function fetchOceMinimalMain() {
      const data = await getItem('minimalmain', 'fields.headerlogo,fields.footerlogo,fields.pages');
      if (!data.hasError) {
        const { fields } = data;
        const { headerlogo, footerlogo } = fields;
        // Extract the sourceset for the headerImage and footerImage and put it back in the data
        data.headerRenditionURLs = getSourceSet(headerlogo);
        data.footerRenditionURLs = getSourceSet(footerlogo);
      }
      return data;
    }

對於呈現影像,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;
    }

fetchPage() 方法會使用網頁的網址代稱值擷取內容類型 MinimalPage。

export async function fetchPage(pageslug) {
      // Get the page details
      const page = await getItem(pageslug, 'fields.sections');
      return page;
    }

getRenditionURLs() 方法會使用影像的 ID,擷取區段中可能定義之任何影像的轉譯 URL。

export function getRenditionURLs(identifier) {
      const client = getClient();
      return client.getItem({
        id: identifier,
        expand: 'fields.renditions',
      }).then((asset) => getSourceSet(asset))
        .catch((error) => logError('Fetching Rendition URLs failed', error));
    }

現在我們有資料查詢,我們可以在我們的 Next.js 元件中轉譯回應。

Next.js 元件

Next.js是以React為基礎, React使用JSX (JavaScript的HTML語法副檔名)來呈現內容。雖然您可以撰寫純 JavaScript 來呈現 Oracle Content Management 的資料,但強烈建議您使用 JSX。

最小的網站應用程式會將每個頁面細分為數個較小的元件。

以下幾節包含 Next.js 在我們的每個元件中如何呈現應用程式的概述:

頁面資料夾

我們的網站提供一個路由-/頁面。要求會導向至 pages/page/[.. slug]].jsx 檔案中定義的主要元件。根路徑要求會透過在 next.config.js 中指定重新導向,重新導向至/page。

  async redirects() {
        return [
          {
            source: '/',
            destination: '/page/',
            permanent: true,
          },
        ]
      }

所有頁面都有包含公司標誌與連結的表頭,以及包含標誌與社交媒體圖示的表尾。透過靜態 URL 存取頁面,並取得將任何相關資料傳送至任何子項元件之前所需的所有資料。

Next.js 會將頁面目錄中的任何頁面視為應用程式的路由。

主要成分

所有頁面均由主要元件轉換,位於 pages/page/[.. slug]].jsx。藉由在雙括弧 ([[…slug]]) 中包含參數,可選擇性地擷取 Next.js 中的所有路由。預設為網頁清單中第一頁的根網頁沒有傳遞的參數,因此我們會將網址代稱參數定義為選擇性。

元件會匯入 API 以從 services.js 檔案取得資料。

import { fetchOceMinimalMain, fetchPage, getRenditionURLs } from '../scripts/services';

頁面的 URL 是動態 URL,其中包含頁面網址代稱作為路徑,範例 URL 路徑為

Next.js 針對具有動態 URL 的頁面使用靜態網站產生時,會呼叫 getStaticPaths() 來取得該頁面的所有路徑。

export async function getStaticPaths() {
      const appData = await fetchOceMinimalMain();
      const { fields } = appData;
    
      // Generate the paths we want to pre-render based on posts
      const paths = fields.pages.map((page) => ({
        params: { slug: [page.slug] },
      }));
      // Also add the path for the root /
      paths.push({
        params: { slug: [] },
      });
      return {
        paths,
        fallback: false,
      };
    }

getStaticProps() 函數可用來取得頁面單一執行處理的資料。頁面網址代稱是從傳送至方法的參數取得。接著會使用頁面網址代稱來取得此頁面所需的所有資料。

export async function getStaticProps(context) {
      // fetch the minimal main data
      const appData = await fetchOceMinimalMain();
      // find the slug param from the context. If its null, default to the first page slug
      const { params } = context;
      let { slug } = params;
      if (slug == null) {
        slug = appData.fields.pages[0].slug;
      }
      // fetch the page corresponding to the slug
      const pageData = await fetchPage(slug);
      const { headerRenditionURLs, footerRenditionURLs, fields } = appData;
      const { sections } = pageData.fields;
    
      // for each section in the page, if a image is present, get the corresponding rendition urls
      // and insert it back into the section
      const promises = [];
      sections.forEach((section) => {
        // add a promise to the total list of promises to get any section rendition urls
        if (section.fields.image) {
          promises.push(
            getRenditionURLs(section.fields.image.id)
              .then((renditionURLs) => {
                // eslint-disable-next-line no-param-reassign
                section.renditionURLs = renditionURLs;
              }),
          );
        }
      });
    
      // execute all the promises and return all the data
      await Promise.all(promises);
      return {
        props: {
          headerRenditionURLs,
          footerRenditionURLs,
          pages: fields.pages,
          pageData,
        },
      };
    }

頁面元件

「頁面」元件負責呈現為頁面定義的所有區段。開啟「頁面」元件,位於 components/Page.jsx。它只會使用從主要元件傳送給它的資料。它不會從伺服器取得任何其他資料。它使用「區段」元件來呈現區段資料。

Page.propTypes = {
      pageData: PropTypes.shape().isRequired,
    };

「標頭」元件 (位於 components/Header.jsx) 和「頁尾」元件 (位於 components/Footer.jsx) 只會使用從「主要」元件傳送給它們的資料。它們不會從伺服器取得任何其他資料。

段落元件

位於 components/Section.jsx 的「區段」元件由「頁面」元件使用,用來呈現 MinimalSection 類型的任何內容項目。

此元件有從「頁面」元件傳送給它的資料。

錯誤元件

「頁面」和「主要」元件會使用位於 components/Error.jsx 的「錯誤」元件。如果在呼叫伺服器期間發生任何錯誤,就會轉換這些錯誤。

作業 3:準備應用程式以進行建置

現在我們已建立 Next.js 部落格網站,我們必須在本機開發伺服器中看到此網站,以便為任何問題除錯,並在應用程式上線前預覽該應用程式。

使用兩個步驟準備應用程式以進行部署:

  1. 調整本機開發伺服器
  2. 使用命令檔在開發和生產環境中建置和執行應用程式

微調本機開發伺服器

您可以執行下列命令,在本機啟動開發伺服器。

npm run dev

然後,將您的瀏覽器開啟到http://localhost:3000,即可查看您的網站如何運作。

注意:這不會預先呈現頁面。若要預先呈現頁面,請參閱下一節。

使用命令檔在開發和生產環境中建置及執行應用程式

如果是實際環境執行,會使用組建命令檔以靜態方式產生網站。

npm run build

啟動命令檔是用來啟動提供靜態產生之頁面的 Node.js 伺服器。

npm run start