ドキュメント

Next.jsの静的サイト生成(SSG)でhacoCMSを使う ​

本チュートリアルでは、Next.jsの静的サイト生成(Static Site Generation, SSG)機能を用いて簡易ブログサイトを構築します。 ​

本チュートリアルでは、Next.jsの静的サイト生成(Static Generation)機能を用いて簡易ブログサイトを構築します。

この簡易ブログサイトは、トップページと記事ページの2種類のページで構成されます。

/           ... トップページ
/post/[id]  ... 記事ページ([id]にはコンテンツIDが入ります)

前提

本チュートリアルでは、以下の内容については前提知識とし、説明を省略します。

  • hacoCMSのアカウント開設と、プロジェクトおよびAPIの作成方法について把握していること。これらについてはhacoCMSのドキュメントをご確認ください。
  • Node.jsの実行環境が整っていること。本チュートリアルではnode, npm, npxを使用します。参考リンク:Node.js公式サイト https://nodejs.org/ja/
  • JavaScriptでのプログラミングがある程度できること。

Step 1. hacoCMSのAPIスキーマ設定

お持ちのhacoCMSアカウントの適当なプロジェクト(無ければ作成してください)に、ブログ記事のAPIを以下の設定で作成してください。APIの作成方法についてはhacoCMSのドキュメントをご確認ください。

  • API名:記事(任意)
  • エンドポイント:entries
  • 説明文:(任意)
  • APIの型:リスト形式
  • APIスキーマ:下記の表と画像を参照
# フィールドタイプ フィールド名(任意) フィールド ID
1 テキストフィールド タイトル title
2 テキストフィールド 概要 description
3 リッチテキスト 本文 body

APIスキーマの設定画面は以下のようになります。

記事APIを作成できたら、適当な記事をいくつか作成してみましょう。コンテンツの作成方法についてはhacoCMSのドキュメントをご確認ください。

Step 2. Next.jsプロジェクトの初期設定

Next.jsプロジェクトを作成します。下記のコマンドを実行して、プロジェクトの初期設定を行います。本チュートリアルではNext.js公式のサンプルプロジェクト https://github.com/vercel/next.js/tree/canary/examples/dynamic-routing をベースにします。

下記のコマンドを実行して、プロジェクトの初期設定を行います。

$ npx create-next-app simple-blog --use-npm --example "https://github.com/vercel/next.js/tree/canary/examples/dynamic-routing"

設定が完了したら、作成されたディレクトリに移動して、初期状態でサイト生成をしてみましょう。

$ cd simple-blog
$ npm run build
$ npm run start

npm run buildによって静的サイトのビルドが行われます。npm run startはビルドしたサイトをホスティングするサーバを起動するコマンドです。

npm run startを実行した状態で、ブラウザで http://localhost:3000/ にアクセスしてみましょう。「Hello World!」などが書かれたページが表示されれば成功です。

Step 3. hacoCMS SDKのインストール

hacoCMS APIをJavaScriptから呼び出すためのSDKであるhacocms-js-sdkをインストールします。下記のコマンドを実行してください。

$ npm install hacocms-js-sdk

Step 4. 簡易ブログサイトのコーディング

このステップで作成するコードの完成形がGitHubにありますので、必要に応じてご参照ください。

トップページ(記事一覧)の作成

まずはトップページを作ってみましょう。最近5件の記事をリスト表示するようにします。

pages/index.jsの編集

テキストエディタでpages/index.jsを開いて、ファイルの冒頭に下記を追加してください。

import { HacoCmsClient, SortQuery } from 'hacocms-js-sdk'

さらに、getStaticProps関数を以下のように定義します。なお、SUBDOMAINは プロジェクト設定 > プロジェクト基本設定 のサブドメインに、ACCESS_TOKENは プロジェクト設定 > APIトークン のAccess-Tokenに、それぞれ置き換えてください。

export async function getStaticProps() {
  // (1) プロジェクト基本設定画面のサブドメインに置き換えてください。
  const PROJECT_SUBDOMAIN = 'SUBDOMAIN'

  // (2) プロジェクトの Access-Token に置き換えてください。
  const PROJECT_ACCESS_TOKEN = 'ACCESS_TOKEN'

  // API の利用に必要なクライアントを生成します。
  const client = new HacoCmsClient(`https://${PROJECT_SUBDOMAIN}.hacocms.com`, PROJECT_ACCESS_TOKEN)

  // hacoCMS の記事 API /entries に GET リクエストを送信し、最近 5 件の記事一覧が入ったレスポンスを受け取ります。
  const res = await client.getList(Object, '/entries', { s: SortQuery.build(['createdAt', 'desc']), limit: 5 })

  // 記事の一覧は res.data に入っているので取り出します。
  const recentEntries = res.data

  return {
    props: {
      recentEntries,
    },
  }
}

そして、const Home = () => ( ... )を次のように書き換えます。

// getStaticProps が返す recentEntries を受け取るようにします。
const Home = ({ recentEntries }) => (
  <>
    <Header />
    <h1>Hello World!</h1>
    {recentEntries.map((post) => (
      <section key={post.id}>
        <h2>
          <Link href={`/post/${post.id}/`}>{post.title}</Link>
        </h2>
        <p>{post.description}</p>
      </section>
    ))}
  </>
)

Next.jsのテンプレートについての説明は公式リファレンス等に譲りますが、recentEntriesの要素をmapメソッドで取り出して参照できるのが見て取れると思います。

ここまでで、一度サイトを生成し直して表示を確認してみましょう。下記のコマンドを実行してください。

$ npm run build
$ npm run start

ブラウザで http://localhost:3000/ にアクセスしてください。hacoCMSで作成したコンテンツの内容がページに反映されているはずです。

個別記事ページの作成

続いて、個別の記事ページを作ってみましょう。

pages/post/[id]/index.jsの編集

pages/post/[id]/index.jsを開いて、既存のimportに続けて下記を追加します。

import { HacoCmsClient } from "hacocms-js-sdk";

// (1) プロジェクト基本設定画面のサブドメインに置き換えてください。
const PROJECT_SUBDOMAIN = 'SUBDOMAIN'

// (2) プロジェクトの Access-Token に置き換えてください。
const PROJECT_ACCESS_TOKEN = 'ACCESS_TOKEN'

const client = new HacoCmsClient(`https://${PROJECT_SUBDOMAIN}.hacocms.com`, PROJECT_ACCESS_TOKEN)

/** 生成するすべての記事ページの [id] を返す */
export async function getStaticPaths() {
  const paths = (await client.getList(Object, '/entries')).data.map(({ id }) => ({ params: { id } }))
  return {
    paths,
    fallback: false,
  }
}


/** 各記事ページ /post/[id] の生成に使用するデータを返す */
export async function getStaticProps({ params }) {
  const entry = await client.getContent(Object, '/entries', params.id)
  return {
    props: {
      entry,
    },
  }
}

そして、const Post = () => { ... }を次のように書き換えます。

// getStaticProps が返す entry を受け取るようにします。
const Post = ({ entry }) => (
  <>
    <Header />
    <h1>{entry.title}</h1>
    <main dangerouslySetInnerHTML={{ __html: entry.body }} />
    <Link href="/">Back to Home</Link>
  </>
)

maindangerouslySetInnerHTML={{ __html: entry.body }}は、entry.bodyに入っているリッチテキストのHTMLをそのまま挿入するためのものです。

できたら、サイトを生成し直して表示を確認してみましょう。

下記のコマンドを実行してください。

$ npm run build
$ npm run start

ブラウザでhttp://localhost:3000/にアクセスして、記事のリンクをクリックしてみてください。個別記事ページへ遷移できるはずです。

なお、hacoCMS でコンテンツを追加・変更・削除した場合は、都度サイトを生成し直す必要があります。

まずは無料でお試しください

メールアドレスのみで簡単に登録できます。
データ設計と運用を簡単に行えるhacoCMSを是非お試しください。

お気軽にお問い合わせください

コンテンツ管理システムの導入を検討されている方へ。
ヘッドレスCMS「hacoCMS」を活用したご提案をいたします。