Logo Image

Blog Article

TypeScriptとNext.jsとmicroCMSでブログサイトを構築してみた

00

今回は、TypeScriptとNext.jsとmicroCMSを使って、シンプルなブログサイトを構築する方法を紹介します。コンテンツの管理が簡単になり、効率的にブログを作成できます。

参考

https://blog.microcms.io/microcms-next-jamstack-blog/

ソフトウェアバージョン
  • Next 15.1.3
  • react 19.0.0
  • react-dom 19.0.0
  • microcms-js-sdk 3.2.1
今回のソースコード

https://github.com/kakuta0915/blog-tutorial.git

microCMSとは?

まず、microCMSについて簡単に説明します。

microCMSは、コンテンツ管理システム (CMS)で、ブログやWebサイトのコンテンツを簡単に管理できるサービスです。データをAPIとして提供してくれるので、Next.jsなどのフレームワークと組み合わせることで、動的なサイトを簡単に構築できます。

microCMSを使うと、サイトのコンテンツ (記事や画像、カテゴリなど) を管理者画面から簡単に追加・編集でき、APIでそのデータを取得して、Webサイトに表示することができます。

1. Next.jsのプロジェクト作成

まず、Next.jsのプロジェクトを作成します。Next.jsはReactのフレームワークで、静的サイトや動的サイトを簡単に作成できます。

TypeScriptの利点

TypeScriptは型を付けることで、コードのエラーを事前に防ぐことができます。さらに、実行する前にエラーを検知するため、デバッグの時間が短縮できます。

Next.jsの利点
  • サーバーサイドレンダリング (SSR)

    ページをサーバー側で生成し、HTMLとして送るのでSEO (検索エンジン最適化)に優れています。よって、ブログ記事が検索エンジンで上位に表示されやすくなります。

  • 静的サイト生成(SSG)

    ビルド時にHTMLを生成しておき、高速にページを表示できます。

プロジェクトを作成

ターミナルを開き、以下のコマンドを実行してNext.jsのプロジェクトを作成します。

これで、Next.jsとTypeScriptが設定されたプロジェクトが作成されます。

npx create-next-app@latest <プロジェクト名> --typescript

プロジェクトのディレクトリに移動して、ローカルサーバーが立ち上がるかを確認しておきます。

npm run dev

ローカルサーバーで立ち上がりました!

2. microCMSの設定

microCMSにサインイン

まず、microCMSの公式サイトで無料アカウントを作成します。

サインイン後、「一から作成する」を選択します。

サービスを作成

サービス名・サービスIDを入力し、作成します。今回はどちらもmy-blog-tutorialとします。

APIの作成

サービスの作成が完了したら、管理画面からAPIの作成をします。「自分で決める」を選択します。

API名とエンドポイントを作成します。今回はblogとしました。

APIの型を選択します。

次に、APIスキーマの設定をします。

APIスキーマとは、microCMSで管理するデータ (ブログ記事)の構造やルールを定義する仕組みのことです。APIスキーマを設定することで、どのようなデータを扱うのか、どんな形式でデータを保存するのかを決めることができます。例えば、記事のタイトルや投稿日、コンテンツ内容などがあります。

最初は、分かりやすくブログ記事のタイトルと本文を追加します。APIスキーマは後で追加できます。

作成後、管理画面からAPIを選択しコンテンツを追加します。

簡単なコンテンツを追加して公開ボタンを押すと、投稿完了です。

これでAPIの準備が完了しました。

3. 記事データを取得するための設定

microCMSからデータを取得するための設定

Next.jsとmicroCMSを連携するにはSDKをインストールする必要があります。

SDKとは、microCMSのAPIを簡単に扱うためのツールキットです。これを使うと、microCMSが提供するAPIエンドポイントへのリクエストを自分で作成しなくても、データの取得や登録、更新などを簡単に行うことができます。

https://www.npmjs.com/package/microcms-js-sdk

npm install microcms-js-sdk

APIキーを作成

ルートディレクトリ直下に.env.localを作成し、APIキーを作成します。

APIキーは、microCMSの【権限管理 → 1個のAPIキー】にあります。

APIキーや機密情報をコード内に直接書いてしまうと、GitHubにプッシュした際に公開されてしまう可能性があります。そのため、.env.localに機密情報を記載し、外部に公開されないようにします。

API_KEY=1wfganwogjwofajfoijweofjewrpiorgr3940

microCMSとの接続設定

ルートディレクトリ直下にlibs/client.jsを作成します。

そしてclinet.jsに以下のコードを記述します。

import { createClient } from "microcms-js-sdk";

export const client = createClient({
  serviceDomain: "my-blog-tutorial",
  apiKey: procces.env.API_KEY,
});

serviceDomainは、作成したサービスのhttps://”XXXXX”.microcms.ioのXXXXXになります。

これでmicroCMSとの接続設定は完了です。

4. データを取得して表示する

SSGでデータを取得

SSGは、ウェブサイトを構築する際に 静的なHTMLファイルを事前に生成する手法を指します。ユーザーがページをリクエストする前に、サーバー側でHTMLが用意されるため、ページの読み込みが非常に高速であるという特徴があります。主に更新頻度が低い場合に利用されます。

src/page/index.tsxにSSGを記述してブログデータを取得します。

  • client.get は、microCMSのSDKを利用してデータを取得するためのコードです。
  • endpoint: "blog"では、microCMSのブログデータを取得しています。
  • data には、microCMSから取得したブログのデータが入ります。
import { GetStaticProps } from "next";
import { client } from "../../libs/client";

export const getStaticProps: GetStaticProps = async () => {
  const data = await client.get({
    endpoint: "blog",
  });

  return {
    props: {
      data.contents,
    },
  };
};

取得した記事データを表示

次に、取得した記事データを表示します。

まず、コードの最初でブログ記事のデータ構造とコンポーネントに渡すデータの型を定義します。

これにより、受け取るデータ構造を明確にして、コードの安全性を高めています。

interface Blog {
  id: string;    // ブログ記事の一意のID
  title: string; // ブログ記事のタイトル
}

interface HomeProps {
  blogs: Blog[]; // 複数のブログ記事を配列で受け取る
}

メインのReactコンポーネントです。

{ blogs }: HomeProps:

  • コンポーネントに渡されるpropsを分解して、blogsだけを受け取っています。
  • HomeProps型を指定しているので、blogsの中身は Blog[]( ブログ記事の配列) であることが保証されています。
export default function Home({ blogs }: HomeProps) {
return (
  <div>
    <h1>ブログ記事一覧</h1>
    <ul>
      {blogs.map((blog) => (
        <li key={blog.id}>
          <a href={`/blog/${blog.id}`}>{blog.title}</a>
        </li>
      ))}
    </ul>
  </div>
);
  • blogs.map((blog) => ...): ブログ記事の配列をループして、それぞれのブログ記事をリストアイテムとして作成しています。
  • <li key={blog.id}>: 各リストアイテムにはユニークなキー (blog.id)を設定します。Reactではキーが必要です。
  • <a href={/blog/${blog.id}}>{blog.title}</a>:
    • 記事タイトルがリンクになっています。
    • クリックすると、/blog/記事ID に移動します。

コード全体がこんな感じです。

import Link from "next/link";
import { GetStaticProps } from "next";
import { client } from "../../libs/client";

interface Blog {
  id: string;
  title: string;
}

interface HomeProps {
  blogs: Blog[];
}

export default function Home({ blogs }: HomeProps) {
  return (
    <div>
      <h1>ブログ記事一覧</h1>
      <ul>
        {blogs.map((blog) => (
          <li key={blog.id}>
            <Link href={`/blog/${blog.id}`}>{blog.title}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

// getStaticProps を使って静的データを取得
export const getStaticProps: GetStaticProps = async () => {
  const data = await client.get({ endpoint: "blog" });

  return {
    props: {
      blogs: data.contents,
    },
  };
};

ブログの記事一覧を取得して表示できました!

5. ブログの詳細ページを表示する

ブログ一覧を取得して表示できましたが、ブログの詳細ページを作成していないのでエラーが出ます。

なのでNext.jsの動的ルーティングを利用して、ブログの記事詳細ページを作成します。動的ルーティングを使えば、複数の記事を1つのテンプレートで表示できるようになります。

動的ルーティングとは?

動的ルーティングは、Next.jsで特定のパラメータ (IDなど)に基づいてページを生成する機能です。

例えば、/posts/123/posts/456 など、異なるURLに対応したページを1つのテンプレートで構築できます。

記事詳細ページのファイル作成

まず、pagesディレクトリに、動的ルーティング用のファイルを作成します。Next.jsでは、以下のようにファイル名を[]で囲むことで動的ルーティングを設定します。

このファイルが、ブログ記事詳細ページを担当します。

src/pages/blog/[id].tsx

getStaticPathsでパスを生成します。

動的ルーティングでは、getStaticPathsを使って事前に生成するページのパス (URL) を指定します。

以下のコードを、[id].tsxに記述します。

import { GetStaticPaths, GetStaticProps } from "next";
import { client } from "../../../libs/client";

export const getStaticPaths: GetStaticPaths = async () => {
  // microCMSから記事データを取得
  const data = await client.get({ endpoint: "blog" });

  // 記事ごとのパスを生成
  const paths = data.contents.map((content: { id: string }) => ({
    params: { id: content.id },
  }));

  return {
    paths,
    fallback: false, // 存在しないパスは404エラーを表示
  };
};
  • lient.get:microCMSのAPIを呼び出し、ブログ記事の一覧データを取得します。
  • data.contents.map:取得したデータのidを元に、動的なパスを生成します。
  • fallback: false:指定されていないパスは404エラーにします。

次に、[id].tsx内に getStaticPropsを使って、一つ一つのブログの詳細データを取得するための記述をします。

import { GetStaticProps } from "next";
import { client } from "../../../libs/client";

export const getStaticProps: GetStaticProps = async (context) => {
  // パスから記事IDを取得
  const id = context.params?.id;

  // microCMSから記事データを取得
  const data = await client.get({
    endpoint: "blog",
    contentId: id as string,
  });

  return {
    props: {
      blog: data,
    },
  };
};
  • context.params?.id:動的ルートのidを取得します。
  • client.get:microCMSのAPIを利用して、指定された記事データを取得します。
  • props:取得した記事データをコンポーネントに渡します。

最後に、取得した記事データを使ってページをレンダリングします。

import { FC } from "react";

type BlogProps = {
  blog: {
    title: string;
    publishedAt: string;
    body: string;
  };
};

const Blog: FC<BlogProps> = ({ blog }) => {
  return (
    <div>
      <h1>{blog.title}</h1>
      <p>{blog.publishedAt}</p>
      <div
        dangerouslySetInnerHTML={{
          __html: blog.body,
        }}
      />
    </div>
  );
};

export default Blog;
  • blog.title:記事のタイトルを表示します。
  • blog.publishedAt:記事の公開日を表示します。
  • dangerouslySetInnerHTML:HTML形式のコンテンツを安全に表示するために使用します。

記事詳細ページが無事に表示されました!

あとはCSSでデザインを整えれば完成です。ビルドやデプロイなど公開に向けた作業もありますが、今回は割愛します。

スタイルを当てたり、デプロイしたい方はmicroCMSの公式ドキュメントをご覧ください。

https://blog.microcms.io/microcms-next-jamstack-blog/

コメント

ログインしてコメントしましょう。