1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Oracle Content ManagementをHeadless CMSとして使用したWebサイトをGatsbyで開発する

Last updated at Posted at 2021-09-03

はじめに

この記事では

  • Always Free(永年無償)で利用できるOracle Content Management - Starter Edition
  • Reactベースの静的サイトジェネレータであるGatsby

を利用し、Oracle Content Management(以降OCM)のアセットリポジトリで管理・公開されるアセットをGatsbyで開発したWebサイトに表示できるようにします

実現したいこと

image.png

  • OCMをHeadless CMSとして利用できるように構成
  • Gatsbyで作成したWebサイトに、OCMで作成・公開したアセットを表示
  • Gatsby → OCMのアセット情報の取得は、GraphQLを利用
  • ページ構成は、ニュース記事のアセットを新着順に一覧表示するインデックスページと、ニュース記事の詳細表示するページ、のシンプルな構成

ツール/サービスとそのバージョン

  • Oracle Content Management - Starter Edition: 21.7.1
  • Git: 2.30.0
  • Node.js: v14.17.5
  • Gatsby CLI: 3.12.0

準備

OCM - Starter Edition 環境の準備

インスタンス作成とアセット登録・公開

OCM - Starter Edition とは、Oracle Cloud Always Free(無償かつ期間の制限無し)で利用できるOCMの機能限定版です。

以下の記事を参考に、OCM - Starter Edition環境を作成します。

最終的には、以下のような形でアセット・リポジトリ内に2件のアセット(画像とコンテンツ・アイテム)が登録された状態になります
image.png

コンテンツ・アイテムは、sampleNewsTypeというコンテンツ・タイプより作成されます。sampleNewsTypeは、タイトル(title)メイン画像(image)ニュース本文(body)の3つのデータ・フィールド(属性)から構成されます。
image

チャネル・トークンの確認

このアセットリポジトリには、sampleChannel という公開チャネルが設定されます。Gatsbyからアセットを参照する際に、このsampleChannelチャネル・トークンを利用します

チャネル・トークンは、OCMのUIからADMINISTRATION:コンテンツチャネルのパブリッシュsampleChannel右上のサイドパネルボタンAPIより確認できます。このチャネル・トークンをメモします

image.png

Gatsby 環境の準備

Gatsbyの環境を準備します。Gatsbyの公式チュートリアルもあわせてご確認ください

事前準備

  • Node.js と git をインストールします

  • gatsby-cliをインストールします

npm install -g gatsby-cli

Gatsbyプロジェクトの作成と起動

  • Gastbyプロジェクトを作成します。ここではプロジェクト名をmy-gatsby-siteとします。また、テンプレートはデフォルトのgatsby-starter-defaultが適用されます
gatsby new my-gatsby-site
  • 作成されたプロジェクトフォルダに移動し、開発サーバを起動します
cd my-gatsby-site
gatsby develop
  • 以下のメッセージが表示されることを確認します
You can now view gatsby-starter-default in the browser.
⠀
  http://localhost:8000/
⠀
View GraphiQL, an in-browser IDE, to explore your site's data and schema
⠀
  http://localhost:8000/___graphql
  • ブラウザでhttp://localhost:8000/を開きます。gatsby-starter-defaultで作成されたサイトを確認できます
    image.png

OCMプラグイン

OCMプラグインは以下サイトで提供されています。

OCMプラグインのインストール

  • my-gatsby-siteのプロジェクトフォルダで、以下コマンドを実行します
npm install @oracle/gatsby-source-oce

gastby-config.jsの編集

インストールされたOCMプラグイン(gatsby-source-oce)を利用するには、gastby-config.jsのプラグインリストにgatsby-source-oceを追加する必要があります

  • エディタ等でgastby-config.jsを開きます

  • plugins:[ ]に gatsby-source-oceの記述を追加します。以下は追加例です

gastby-config.js
module.exports = {
  siteMetadata: {
    title: `Gatsby Default Starter`,
    description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
    author: `@gatsbyjs`,
    siteUrl: `https://gatsbystarterdefaultsource.gatsbyjs.io/`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    `gatsby-plugin-image`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },

    ========== (※途中省略) ==========

    `gatsby-plugin-gatsby-cloud`,
    // this (optional) plugin enables Progressive Web App + Offline functionality
    // To learn more, visit: https://gatsby.dev/offline
    // `gatsby-plugin-offline`,
    {
      resolve: `@oracle/gatsby-source-oce`,
      options: {
        name: `oce`,
        contentServer: `https://snakaocmse-orasejapan.cec.ocp.oraclecloud.com`,
        channelToken: `e38f35f1fece4b309350b97907c08811`,
        proxyUrl: ``,
        items: {
          limit: 100,
          query: ``,
        },
        renditions: `all`,
        preview: false,
        auth: ``,
        staticAssetDownload: `true`,
        staticAssetRootDir: `asset`,
      },
    },
  ],
}

[説明]構成オプションについて

構成オプションについて簡単に説明します。詳細はこちらのサイトでご確認ください

  • contentServer(必須)
    • アセットを取得するOCMインスタンスのURLを指定
    • 形式はhttps://<インスタンス名>-<テナンシー名>.cec.ocp.oraclecloud.com
  • channelToken(必須)
    • アセットを取得する公開チャネルのチャネルトークンを指定
    • 準備段階でメモしたチャネルトークンを指定
  • renditions(任意)
    • ビルド実行時に、デジタルアセットの自動生成されるレンディション(システムレンディション)を公開サイトのディレクトリにダウンロードするか?(しないか?)を指定
    • 以下3つが指定できます
      • custom(デフォルト): カスタムレンディションのみダウンロードする
      • none: レンディションはダウンロードしない
      • all: システムレンディション(Large/Medium/Small/Thumbnail)とカスタムレンディションを含むすべてのレンディションをダウンロードする
    • 今回はallを指定
  • staticAssetDownload(任意)
    • ビルド実行時に、デジタルアセットのバイナリファイルを公開サイトのディレクトリにダウンロードするか?(しないか?)を指定
    • trueまたはfalse(デフォルト) を指定
    • 今回はtrueを指定
  • staticAssetRootDir(任意)
    • デジタルアセットのダウンロード先のディレクトリを指定
    • staticAssetDownloadtrueの場合のみ有効
    • デフォルトはasset
    • 今回はデフォルト値(asset)をそのまま利用

[説明]デジタルアセットのダウンロード設定について

今回の設定は以下のとおりです

  • renditions = all
  • staticAssetDownload = true
  • staticAssetRootDir = asset

デジタルアセットSampleImage1.jpgをGatsbyサイトで利用した場合、SampleImage1.jpgは以下のように公開サイトのディレクトリにダウンロードされます

  • /asset/SampleImage1.jpg (オリジナルファイル/原本ファイル)
  • /asset/Large/SampleImage1.jpg (Largeレンディション)
  • /asset/Medium/SampleImage1.jpg (Mediumレンディション)
  • /asset/Small/SampleImage1.jpg (Smallレンディション)
  • /asset/Thumbnail/SampleImage1.jpg (Thumbnailレンディション)

例えは、Webページ上でThumbnailレンディションを表示する場合は、<img src="/asset/Thumbnail/SampleImage1.jpg" />と指定します

renditionsにallを設定すると、Gatsbyはオリジナルの画像とシステムレンディション(Thumbnail,Smallなど)の両方を、すべての公開済のデジタル・アセットに対して取得・生成します。これにより、ビルドプロセスに多くの処理時間とネットワーク負荷が発生する可能性があります。自動生成されるレンディションを明示的に使用する場合を除いて、noneまたはcustomオプションの使用を推奨します

確認

開発環境を起動し、レンディションがダウンロードされているか?を確認します、また、ブラウザ上でクエリを実行できるGraphiQLを使ってアセットが取得できるか?を確認します

レンディションのダウンロードを確認

  • 開発環境を起動(起動中の場合はControl-Cで停止→起動)します
gatsby develop
  • my-gatsby-siteのプロジェクトのpuclicフォルダ配下にassetが作成されます。その中にオリジナルファイルと各レンディションファイルがダウンロードされます
    image.png

  • ブラウザで http://localhost:8000/asset/Thumbnail/SampleImage1.jpgを開きます。サムネイルサイズの画像が表示できます
    image.png

GraphiQLでOCMのアセットを取得する

  • ブラウザでhttp://localhost:8000/___graphqlを開きます。左側のExplorerallOceAssetoceAssetが表示されることを確認します
    image.png

  • allOceAssetをクリックすると、クエリを展開してくれます。今回はsampleNewsTypeアセットタイプのidnameoceIdslugを取得します

  • filter > oceType を開き、eq:を選択します

  • eq: の隣の " " の中にsampleNewsTypeを入力し、実行(画面上の横向き三角ボタン)をクリックします
    image.png

  • 結果が右ペインに表示されます。edges>node>idが自動的に追加されます。このedges>node配下にアセットの基本情報や属性情報があります
    image.png

  • edges>node配下のidnameoceIdslugの4項目を選択し、クエリを実行します。指定したアセット・タイプのコンテンツ・アイテムの一覧が取得できます(今回の場合、2件のコンテンツ・アイテムを取得)
    image.png

  • コンテンツ・アイテムの属性情報も取得する場合は、edges>node>oceFieldsを展開します。ここではtitlebodyを追加で選択し、クエリと実行します。コンテンツ・アイテムの**title(タイトル)body(本文)**が取得できます
    image.png

  • クエリで取得した情報をソートする場合は、sortを展開し、ソート対象のfieldsorderを指定します。今回は、fieldsに**"updatedDate"order"DESC"**を指定します。実行結果は以下のとおりです

    • image.png

Webページの編集

GatsbyサイトのWebページで、OCMから取得したニュースコンテンツを一覧表示できるようにします

ニュース一覧の表示

GatsbyサイトのWebページにOCMから取得したsampleNewsTypeのニュース・コンテンツの一覧を新着順で表示します

  • my-gatsby-siteプロジェクトのsrc/pages/index.jsを開き、以下の通りに編集します
src/pages/index.js
//index.js
import * as React from "react"
import { graphql } from "gatsby"

import Layout from "../components/layout"
import Seo from "../components/seo"

const IndexPage = ({data}) => {

  const oceposts = data.allOceAsset.nodes

  return(
    <Layout>
      <Seo title="Home" />
      <h1>ニュース一覧</h1>

      {oceposts.map(post => {

        console.log(post)

        return (
          <div key={post.id}>
              <h3>{post.oceFields.title}</h3>
              <img src={"/asset/Thumbnail/" + post.oceFields.image.name} alt={post.oceFields.image.name} />
          </div>
        )
      })}
    </Layout>
  )
}

export const query = graphql`
  {
    allOceAsset(
      filter: {oceType: {eq: "sampleNewsType"}}
      sort: {order: DESC, fields: updatedDate}
    ) {
      nodes {
        id
        oceId
        name
        slug
        oceFields {
          title
          image {
            name
          }
        }
      }
    }
  }
`

export default IndexPage

  • index.jsを保存します

  • 開発環境が起動されていることを確認し、http://localhot:8000/を開きます。ニュース・コンテンツのtitle(タイトル)とimage(メイン画像)のサムネイルサイズの画像が表示されることを確認します
    image.png

説明(index.js)

  • import { graphql } from "gatsby"でgraphQLをインポート

  • const IndexPage = ({data}) => {dataに、後述のgraphqlで取得したデータが受け渡される

  • graphqlのallOceAsset()を利用して、ニュース一覧を表示する際に必要な情報を取得

    • filter: {oceType: {eq: "sampleNewsType"}}で取得するアセット・タイプを指定
    • sort: {order: DESC, fields: updatedDate}でアセットの更新日時順(新→旧)にソート
    • oceIdslugはニュースの詳細ページを表示する際に利用
    • ニュース画像のimageはファイル名(image.name)のみを取得し、ビルド時に公開環境に自動生成されるサムネイル画像をWebページ上で表示(OCMの公開アセットへの直リンクURLは利用しない)

ビルド

  • 開発環境が起動されている場合は、Control-Cで停止します

  • Buildを実行します

gatsby build
  • Buildした内容をローカル環境で確認します
gatsby serve
  • 以下のメッセージが表示されるのを確認し、ブラウザでhttp://localhoat:9000/を開きます
You can now view gatsby-starter-default in the browser.
⠀
  http://localhost:9000/
  • 作成したWebサイトが表示されます
    image.png

ニュースの詳細表示ページ

前の手順で作成したニュース一覧ページ(index.js)は、ニュース一覧を表示するだけでした。
ここでは、ニュース一覧ページでニュースタイトルや画像をクリックすると、ニュースの詳細ページが表示されるようにします

ニュース詳細ページの作成

sampleNewsTypeのニュース・コンテンツを詳細表示するテンプレートを作成します

  • my-gastby-site/src/の下にtemplatesフォルダを作成し、news-post.jsファイルを作成します

  • news-post.jsを以下の通りに編集し、保存します

src/templates/news-post.js
// news-post.js
import * as React from "react"
import { graphql } from "gatsby"

import Layout from "../components/layout"
import Seo from "../components/seo"

const NewsPostTemplate = ({ data }) => {
  const post = data.oceAsset

  console.log(post)

  return (
    <Layout>
    <Seo title={post.oceFields.title} />

      <article>
        <header>
          <h1 itemProp="headline">{post.oceFields.title}</h1>
        </header>

        <img src={"/asset/" + post.oceFields.image.name} alt={post.oceFields.image.name} />

        <section
          dangerouslySetInnerHTML={{ __html: post.oceFields.body }}
          itemProp="articleBody"
        />
      </article>
      <hr />
    </Layout>
  )
}

export default NewsPostTemplate

export const query = graphql`
  query newsquery(
    $id: String
  ){
    oceAsset(oceId: {eq: $id}) {
      id
      slug
      oceId
      oceFields {
        title
        image {
          name
          }
        body
      }
    }
  }
`

説明(news-post.js)

  • graphqlでoceAsset(oceId: {eq: $id})$idはアセットを一意に識別するコンテンツIDを指定

  • 属性フィールドは、title(タイトル)body(本文)imageのname(メイン画像の名前)を取得し、それぞれをページ上にそのまま表示します

  • <img src={"/asset/" + post.oceFields.image.name} alt={post.oceFields.image.name} />でimageのオリジナルファイルを表示します

  • dangerouslySetInnerHTML={{ __html: post.oceFields.body }}で、WYSIWYGエディタで作成した本文がそのままWebページ上に表示されます

gatsby-node.js の編集

my-gatsby-siteフォルダ配下のgatsby-node.jsを編集し、動的なページ生成を実装します。この場合は、ニュース一覧ページからリンクされるニュースの個別詳細ページを、取得したコンテンツ・アイテムの数だけ生成します

  • my-gatsby-site/gatsby-node.jsを開きます。最初は空ページですが、ここに以下のコードを入力します
gatsby-node.js
//gatsby-node.js
const path = require("path");

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;

  const result = await graphql(`
      query {
        allOceAsset(filter: {oceType: {eq: "sampleNewsType"}}) {
          nodes {
            oceId
            slug
            id
          }
        }
      }
  `);

  if (result.errors) {
    throw result.errors;
  }

  const posts = result.data.allOceAsset.nodes;

  posts.forEach((post) => {
    createPage({
      path: `/news/${post.slug}`,
      component: path.resolve(`src/templates/news-post.js`),
      context: {
        id: post.oceId
      },
    });
  });
};

  • gatsby-node.jsを保存します

説明(gatsby-node.js)

  • createPagesのAPIを利用してニュースの詳細ページを生成します。詳細はこちらの公式ドキュメントを参照

  • GraphQLでsampleNewsTypeのコンテンツ・アイテムのoceIdslugidを取得

    • 詳細ページへのパス(URL)は /news/${post.slug}を指定
    • 詳細ページのテンプレートは前の手順で作成した./src/templates/news-post.jsを指定
    • 詳細ページへの引数はcontext: {id: post.oceId}oceId(コンテンツID)を指定

ニュース一覧(index.js)の編集

ニュース一覧ページ(index.js)に詳細ページへのリンクを追加します

  • index.js を開き、以下の通りに編集します
src/pages/index.js
//index.js
import * as React from "react"
import { graphql } from "gatsby"

import { Link } from "gatsby"

import Layout from "../components/layout"
import Seo from "../components/seo"

const IndexPage = ({data}) => {

  const oceposts = data.allOceAsset.nodes

  return(
    <Layout>
      <Seo title="Home" />
      <h1>ニュース一覧</h1>

      {oceposts.map(post => {

        console.log(post)

        return (
          <div key={post.id}>
            <Link to={"/news/" + post.slug} itemProp="url">
              <h3>{post.oceFields.title}</h3>
              <img src={"/asset/Thumbnail/" + post.oceFields.image.name} alt={post.oceFields.image.name} />
            </Link>
          </div>
        )
      })}
    </Layout>
  )
}

export const query = graphql`
  {
    allOceAsset(
      filter: {oceType: {eq: "sampleNewsType"}}
      sort: {order: DESC, fields: updatedDate}
    ) {
      nodes {
        id
        oceId
        name
        slug
        oceFields {
          title
          image {
            name
          }
        }
      }
    }
  }
`

export default IndexPage

説明(index.js)

変更点は以下3点

  • 4行目にimport { Link } from "gatsby"を追加
  • 24行目に<Link to={"/news/" + post.slug} itemProp="url">。リンク先はgatsby-node.jsのパスで指定した通り、/news/(コンテンツ・アイテムのslug)を指定
  • 27行目に</Link>を追加

確認

  • 開発環境を起動します
gatsby develop
  • http://localhost:8000/をブラウザで開きます。以下のように各ニュースに詳細ページへのリンクが設定されます
    image.png

  • ニュース(ここでは「002ニュースのタイトル」)をクリックします。ニュースの詳細ページが表示されます。また、URLも /news/<slug>となっていることを確認します
    image.png

  • 開発環境を停止します。buildし、ローカル環境で実行します

gatsby build
gatsby serve
  • http://localhost:9000/を開き、動作を確認します

おわりに

Oracle Content Management(OCM)のアセットリポジトリで管理・公開されるアセットをGatsbyで作ったWebページに表示する流れを紹介しました。Gatsbyのコーディングは、もっとスマートな方法があると思います。改善点などあれば、お知らせいただけると幸いです

この記事を作成する際に参考にした記事を最後にリンクします(他のHeadless CMS + Gatsbyの実装サンプル方法を参考にしました)

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?