ReactとNext.jsを使ってMarkdownブログを簡単に構築する方法

ReactとNext.jsを利用することで、モダンなウェブ開発の利便性を最大限に活用したMarkdownブログを簡単に構築できます。本記事では、Markdown形式のファイルを使ってブログ記事を管理し、Next.jsの強力な機能を活用して動的に表示する方法を詳細に解説します。特に、フロントエンド開発に馴染みがない方や効率的にブログを構築したい方にとって、基礎から実践的な内容までを網羅したガイドとなります。このアプローチをマスターすることで、自分だけのカスタマイズ可能なブログを短時間で公開できるようになります。

目次

ReactとNext.jsの基礎知識

Reactとは何か


ReactはFacebookが開発したJavaScriptライブラリで、UI(ユーザーインターフェース)を構築するために使用されます。コンポーネントベースのアプローチを採用しており、再利用可能なUI部品を作成することで、効率的かつモジュール化された開発が可能です。

Next.jsとは何か


Next.jsはReactをベースにしたフレームワークで、サーバーサイドレンダリング(SSR)や静的サイト生成(SSG)など、React単体では手間のかかる機能を簡単に実装できます。特に以下の点で強力です。

  • ページの自動的なルーティング
  • 高速なビルドとパフォーマンス最適化
  • 静的サイト生成によるSEOの向上

ReactとNext.jsの組み合わせのメリット

  1. 簡易な開発フロー: Reactの柔軟性とNext.jsの強力なツールを組み合わせることで、開発効率が向上します。
  2. SEO対応: Next.jsのSSRとSSGにより、検索エンジンへのインデックスが容易になります。
  3. 優れたパフォーマンス: 静的サイト生成を活用した高速なウェブサイトを構築可能です。

ReactとNext.jsを組み合わせることで、現代的なウェブアプリケーションの構築が飛躍的に簡単になります。本記事では、この二つを活用して、Markdownブログを効率的に構築する方法を詳しく解説していきます。

必要なツールとセットアップ方法

開発に必要なツール


ReactとNext.jsを使ったプロジェクトを始めるために、以下のツールを準備します:

  • Node.js: JavaScriptの実行環境であり、npm(Node Package Manager)が含まれています。
  • コードエディタ: Visual Studio Code(VS Code)を推奨。拡張機能も豊富です。
  • Git: ソースコードの管理やバージョン管理に利用します。

プロジェクトのセットアップ

  1. Node.jsのインストール
    Node.jsの公式サイト(Node.js公式)からLTS版をダウンロードしてインストールします。
  2. Next.jsプロジェクトの作成
    ターミナルを開き、以下のコマンドを実行します:
   npx create-next-app@latest markdown-blog
   cd markdown-blog
   npm run dev

markdown-blogというフォルダが作成され、Next.jsの基本プロジェクトが初期化されます。npm run devでローカルサーバーが起動し、ブラウザでhttp://localhost:3000にアクセスして動作を確認できます。

  1. 必要なパッケージのインストール
    Markdownの読み込みやパースに使用するライブラリをインストールします:
   npm install gray-matter remark remark-html
  • gray-matter: Markdownファイルのフロントマターを解析します。
  • remarkremark-html: MarkdownをHTMLに変換するためのツールです。

プロジェクト構造の確認


プロジェクトフォルダは以下のようになります:

markdown-blog/
├── pages/
├── public/
├── styles/
├── node_modules/
├── package.json
  • pages: アプリケーションのルーティングを管理します。
  • public: 静的ファイルを格納します。
  • styles: CSSファイルを格納します。

セットアップの完了


ここまでで、Next.jsを利用したプロジェクトの準備が完了しました。次にMarkdownファイルを準備し、ブログの構築に進みます。

Markdownファイルの準備と構造設計

Markdownファイルとは


Markdownは、シンプルな記法で書ける軽量マークアップ言語です。テキストベースでありながら、HTMLに変換してブラウザで表示可能なため、ブログ記事やドキュメントの作成に広く利用されています。

Markdownファイルの作成

  1. プロジェクトのルートディレクトリにpostsフォルダを作成します:
   mkdir posts
  1. postsフォルダ内にMarkdownファイルを作成します。例としてfirst-post.mdを作成します:
   touch posts/first-post.md
  1. 作成したMarkdownファイルに以下の内容を記述します:
   ---
   title: "初めての投稿"
   date: "2024-12-01"
   description: "ReactとNext.jsで作成したMarkdownブログの初投稿です。"
   ---
   # 初めての投稿
   このブログはReactとNext.jsを使って構築されました。Markdownを使って簡単に記事を書くことができます。

Markdownファイルの構造設計


Markdownファイルを効率的に管理するため、以下のようなフォルダ構造を設計します:

markdown-blog/
├── posts/
│   ├── first-post.md
│   ├── second-post.md
  • postsフォルダ: Markdown形式でブログ記事を保存する専用フォルダ。

フロントマターの役割


Markdownファイルの冒頭に記述する---で囲まれた部分を「フロントマター」と呼びます。ここにメタデータ(タイトル、日付、説明など)を記述することで、記事情報を簡単に管理できます。

例:

---
title: "記事タイトル"
date: "記事の日付"
description: "記事の概要"
---

構造の設計のポイント

  1. 一貫性: ファイル名やメタデータの形式を統一することで、記事管理が容易になります。
  2. 拡張性: 必要に応じてタグやカテゴリを追加することで、柔軟に運用可能です。

この準備により、Markdownファイルを簡単に管理し、ブログ記事を効率的に構築できる基盤が整いました。次は、これらのMarkdownファイルをNext.jsで読み込む方法を解説します。

Next.jsでMarkdownを読み込む方法

Markdownの読み込みに必要なライブラリ


MarkdownファイルをNext.jsで動的に読み込むには、以下のライブラリを使用します:

  • fs: ファイルシステムにアクセスするNode.jsの組み込みモジュール。
  • path: ファイルやディレクトリのパス操作を行うためのモジュール。
  • gray-matter: Markdownファイルからフロントマターを解析するライブラリ。

データ取得のセットアップ

  1. プロジェクトのlibフォルダに新しいファイルを作成します:
   mkdir lib
   touch lib/posts.js
  1. lib/posts.jsに以下のコードを記述します:
   import fs from 'fs';
   import path from 'path';
   import matter from 'gray-matter';

   const postsDirectory = path.join(process.cwd(), 'posts');

   export function getSortedPostsData() {
       // postsディレクトリ内のファイル名を取得
       const fileNames = fs.readdirSync(postsDirectory);
       const allPostsData = fileNames.map((fileName) => {
           // 拡張子を除いたファイル名を取得
           const id = fileName.replace(/\.md$/, '');

           // ファイルのフルパスを取得
           const fullPath = path.join(postsDirectory, fileName);
           const fileContents = fs.readFileSync(fullPath, 'utf8');

           // gray-matterを使ってファイルのメタデータを解析
           const matterResult = matter(fileContents);

           // データをオブジェクトとして返す
           return {
               id,
               ...matterResult.data,
           };
       });

       // 日付でソートして返す
       return allPostsData.sort((a, b) => {
           return new Date(b.date) - new Date(a.date);
       });
   }

データ取得関数の使用


Next.jsのgetStaticPropsを使ってブログ記事データをページに渡します。

  1. pages/index.jsを以下のように編集します:
   import { getSortedPostsData } from '../lib/posts';

   export async function getStaticProps() {
       const allPostsData = getSortedPostsData();
       return {
           props: {
               allPostsData,
           },
       };
   }

   export default function Home({ allPostsData }) {
       return (
           <div>
               <h1>Markdownブログ</h1>
               <ul>
                   {allPostsData.map(({ id, title, date }) => (
                       <li key={id}>
                           <a href={`/posts/${id}`}>
                               <h2>{title}</h2>
                               <p>{date}</p>
                           </a>
                       </li>
                   ))}
               </ul>
           </div>
       );
   }

データの確認


サーバーを起動して、ブログ記事がリスト形式で表示されるか確認します:

npm run dev

ブラウザでhttp://localhost:3000にアクセスすると、Markdownファイルに基づいて生成されたブログ記事一覧が表示されます。

ポイント

  • ファイル操作: fspathを使用することで、ローカルのMarkdownファイルを動的に読み込むことができます。
  • データソート: 記事を日付順に並べることで、最新記事が上に表示されるようになります。

次は、記事詳細ページを実装するために動的ルーティングを設定します。

フロントマターの利用とデータ管理

フロントマターとは


フロントマターはMarkdownファイルの冒頭に記述するメタデータで、記事のタイトルや日付、概要などを管理するために使用します。これにより、記事の属性を簡単に設定し、アプリケーション内で利用できます。

例:

---
title: "初めての投稿"
date: "2024-12-01"
description: "ReactとNext.jsで作成したMarkdownブログの初投稿です。"
---
# 初めての投稿
このブログはReactとNext.jsを使って構築されました。

フロントマターの構造と役割

  1. title: 記事のタイトル。ブログリストやページのタイトルタグに使用。
  2. date: 記事の日付。記事の公開順や表示に利用。
  3. description: 記事の概要。SEO対策やブログリストのプレビュー表示に活用。

必要に応じてタグやカテゴリを追加することも可能です:

---
title: "新しい記事"
date: "2024-12-01"
tags: ["React", "Next.js"]
---

フロントマターのデータ管理

記事リストの作成


lib/posts.jsでフロントマターを解析し、必要なデータを管理します:

export function getSortedPostsData() {
    const fileNames = fs.readdirSync(postsDirectory);
    const allPostsData = fileNames.map((fileName) => {
        const id = fileName.replace(/\.md$/, '');
        const fullPath = path.join(postsDirectory, fileName);
        const fileContents = fs.readFileSync(fullPath, 'utf8');
        const matterResult = matter(fileContents);
        return {
            id,
            ...matterResult.data,
        };
    });
    return allPostsData.sort((a, b) => new Date(b.date) - new Date(a.date));
}

この関数は、Markdownファイルからid, title, date, descriptionなどを抽出し、ソートした記事リストを返します。

記事詳細データの取得


記事詳細ページでは、個別記事のデータを取得します:

export function getPostData(id) {
    const fullPath = path.join(postsDirectory, `${id}.md`);
    const fileContents = fs.readFileSync(fullPath, 'utf8');
    const matterResult = matter(fileContents);
    return {
        id,
        content: matterResult.content,
        ...matterResult.data,
    };
}

この関数では、指定されたMarkdownファイルを読み込み、本文(content)とフロントマターをオブジェクトとして返します。

データの活用

記事リストでの表示


pages/index.jsでフロントマターのデータを活用してブログ記事リストを表示します:

export default function Home({ allPostsData }) {
    return (
        <div>
            <h1>Markdownブログ</h1>
            <ul>
                {allPostsData.map(({ id, title, date, description }) => (
                    <li key={id}>
                        <a href={`/posts/${id}`}>
                            <h2>{title}</h2>
                            <p>{description}</p>
                            <small>{date}</small>
                        </a>
                    </li>
                ))}
            </ul>
        </div>
    );
}

記事詳細ページでの使用


フロントマターの情報を用いて記事詳細ページを作成します:

import { getPostData } from '../../lib/posts';

export async function getStaticProps({ params }) {
    const postData = getPostData(params.id);
    return {
        props: {
            postData,
        },
    };
}

export default function Post({ postData }) {
    return (
        <article>
            <h1>{postData.title}</h1>
            <div>{postData.date}</div>
            <div dangerouslySetInnerHTML={{ __html: postData.content }} />
        </article>
    );
}

ポイント

  • メタデータの一元管理: フロントマターに必要な情報を集約することで、記事管理が容易になります。
  • 動的なデータ操作: フロントマターのデータを利用して、柔軟にリスト表示や記事詳細を生成できます。

フロントマターを活用することで、Markdownベースのブログを効率的に管理し、柔軟なデータ操作を可能にします。次は、動的ルーティングを実装して記事詳細ページを構築します。

動的ルーティングの実装方法

Next.jsにおける動的ルーティングとは


動的ルーティングは、URLパラメータに基づいて動的にページを生成する仕組みです。Next.jsでは、[id].jsのようなファイル名を使用して、動的なページルートを作成します。これにより、Markdownブログの記事ごとに個別の詳細ページを生成できます。

動的ルーティングの実装手順

動的ルートファイルの作成

  1. プロジェクトのpages/postsディレクトリに動的ルートを作成します:
   mkdir pages/posts
   touch pages/posts/[id].js
  1. pages/posts/[id].jsに以下のコードを記述します:
   import { getAllPostIds, getPostData } from '../../lib/posts';

   export async function getStaticPaths() {
       const paths = getAllPostIds();
       return {
           paths,
           fallback: false,
       };
   }

   export async function getStaticProps({ params }) {
       const postData = getPostData(params.id);
       return {
           props: {
               postData,
           },
       };
   }

   export default function Post({ postData }) {
       return (
           <article>
               <h1>{postData.title}</h1>
               <p>{postData.date}</p>
               <div dangerouslySetInnerHTML={{ __html: postData.content }} />
           </article>
       );
   }

動的なパスの生成


記事ごとに動的ルートを作成するための関数をlib/posts.jsに追加します:

export function getAllPostIds() {
    const fileNames = fs.readdirSync(postsDirectory);
    return fileNames.map((fileName) => {
        return {
            params: {
                id: fileName.replace(/\.md$/, ''),
            },
        };
    });
}

この関数は、postsディレクトリ内のMarkdownファイル名を元に、動的パスを生成します。getStaticPathsで使用される形式に準拠しており、params.idとして各ファイル名(拡張子を除く)を返します。

記事データの取得


記事詳細ページで表示するデータを取得するため、getPostData関数を活用します。この関数は記事の本文とフロントマターを読み込み、詳細ページで利用します。

動的ページの完成


これらを組み合わせることで、http://localhost:3000/posts/{id}形式のURLに対応する記事詳細ページが生成されます。例えば、first-post.mdの記事がある場合、http://localhost:3000/posts/first-postで表示できます。

ポイント

  • getStaticPathsの役割: 動的に生成するページのパスを指定します。
  • getStaticPropsの役割: 指定されたパスに基づいて必要なデータを取得します。
  • SEOの強化: 各記事ごとに静的ページが生成されるため、検索エンジンへの最適化が容易です。

これにより、Next.jsの動的ルーティングを活用して、Markdownブログの各記事に対応した詳細ページを構築できました。次は、デザインとスタイリングの最適化に進みます。

スタイリングとデザインの最適化

デザインの重要性


ブログのデザインは、訪問者の印象やユーザー体験に大きく影響を与えます。スタイリングを適切に施すことで、読みやすさや見た目の美しさを向上させることができます。ここでは、CSSとUIライブラリを使ってMarkdownブログのデザインを最適化する方法を紹介します。

CSSで基本的なスタイリングを適用する

CSSファイルの追加

  1. プロジェクトのstylesフォルダにglobal.cssを作成します:
   touch styles/global.css
  1. global.cssに基本スタイルを記述します:
   body {
       font-family: Arial, sans-serif;
       line-height: 1.6;
       margin: 0;
       padding: 0;
       background-color: #f4f4f9;
       color: #333;
   }

   a {
       text-decoration: none;
       color: #0070f3;
   }

   a:hover {
       text-decoration: underline;
   }

   h1, h2, h3 {
       margin: 1rem 0;
   }

   ul {
       list-style: none;
       padding: 0;
   }

   li {
       margin: 1rem 0;
   }
  1. このスタイルを適用するために、pages/_app.jsを編集します:
   import '../styles/global.css';

   export default function App({ Component, pageProps }) {
       return <Component {...pageProps} />;
   }

UIライブラリの導入

Tailwind CSSの設定


Tailwind CSSは、効率的なデザインを可能にするユーティリティファーストのCSSフレームワークです。

  1. Tailwind CSSをインストールします:
   npm install tailwindcss postcss autoprefixer
   npx tailwindcss init
  1. tailwind.config.jsを編集し、contentセクションに対象ファイルを指定します:
   module.exports = {
       content: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
       theme: {
           extend: {},
       },
       plugins: [],
   };
  1. Tailwind CSSをglobal.cssで有効化します:
   @tailwind base;
   @tailwind components;
   @tailwind utilities;

スタイリングの適用


pages/index.jsでTailwind CSSを使用してスタイルを適用します:

export default function Home({ allPostsData }) {
    return (
        <div className="max-w-3xl mx-auto p-4">
            <h1 className="text-4xl font-bold mb-6">Markdownブログ</h1>
            <ul>
                {allPostsData.map(({ id, title, date, description }) => (
                    <li key={id} className="mb-4">
                        <a href={`/posts/${id}`} className="block p-4 bg-white rounded shadow hover:shadow-md">
                            <h2 className="text-2xl font-semibold">{title}</h2>
                            <p className="text-gray-600">{description}</p>
                            <small className="text-gray-500">{date}</small>
                        </a>
                    </li>
                ))}
            </ul>
        </div>
    );
}

レスポンシブデザインの対応


Tailwind CSSでは、レスポンシブデザインが簡単に設定できます。例えば、画面幅に応じたスタイルを適用するには以下のように記述します:

<h2 className="text-lg sm:text-xl md:text-2xl lg:text-3xl">タイトル</h2>
  • sm:: 小さなスクリーン向け(640px以上)
  • md:: 中程度のスクリーン向け(768px以上)
  • lg:: 大きなスクリーン向け(1024px以上)

ポイント

  • 簡潔で一貫性のあるデザイン: Tailwind CSSを活用することで、統一感のある美しいデザインを短時間で構築できます。
  • モバイルフレンドリー: レスポンシブデザインを取り入れることで、すべてのデバイスで最適な表示を提供します。
  • 柔軟なカスタマイズ: Tailwind CSSのユーティリティクラスを活用して、自由自在なデザインが可能です。

このステップで、ブログの見た目が大幅に向上し、訪問者にとってより魅力的で使いやすいサイトが完成します。次は、デプロイと公開の手順を説明します。

デプロイと公開の手順

デプロイの準備

プロジェクトのビルド


Next.jsプロジェクトを公開する前に、ビルドを実行して本番環境用の静的ファイルを生成します。以下のコマンドを実行します:

npm run build

これにより、outフォルダに静的ファイルが生成されます。

Gitリポジトリへのコミット


デプロイを容易にするために、プロジェクトをGitHubなどのリポジトリにアップロードします。

  1. Gitリポジトリを初期化します:
   git init
   git add .
   git commit -m "Initial commit"
  1. リモートリポジトリを設定し、プッシュします:
   git remote add origin <リポジトリURL>
   git branch -M main
   git push -u origin main

Vercelを使ったデプロイ

Vercelアカウントの作成

  1. Vercelにアクセスしてアカウントを作成します。
  2. GitHubアカウントと連携しておくと便利です。

プロジェクトのデプロイ

  1. Vercelダッシュボードで「New Project」をクリックします。
  2. GitHubリポジトリを選択して「Import」をクリックします。
  3. デフォルトの設定を確認し、「Deploy」をクリックします。

デプロイが完了すると、Vercelが自動的にプロジェクトをビルドし、公開用のURLが発行されます。

カスタムドメインの設定

  1. Vercelダッシュボードでプロジェクトを開き、「Settings」を選択します。
  2. 「Domains」セクションでカスタムドメインを追加します。
  3. ドメインのDNS設定で、CNAMEレコードをVercelが提供するURLに向けます。

デプロイ後の確認


デプロイが成功したら、発行されたURLにアクセスして動作を確認します:

  • 記事一覧ページと記事詳細ページが正しく表示されるか。
  • リンクやナビゲーションが正常に動作するか。
  • モバイルデバイスでの表示やレスポンシブデザインが期待通りか。

公開後のポイント

  • SEO対策: next-seoなどのライブラリを活用して、メタタグやOGP設定を追加します。
  • パフォーマンス最適化: LighthouseやPageSpeed Insightsでパフォーマンスをチェックし、改善します。
  • 定期的な更新: 新しいMarkdown記事を追加した際に、再デプロイして公開内容を更新します。

Vercelを利用するメリット

  • 無料プランの利用: 小規模なブログには十分な無料プランが用意されています。
  • 簡単な操作: Gitリポジトリと連携するだけでデプロイ可能です。
  • 高速な配信: グローバルなCDNが利用されるため、高速なサイト表示を提供します。

この手順で、あなたのReactとNext.jsを活用したMarkdownブログを世界に公開する準備が整いました。次は全体のまとめに進みます。

まとめ


ReactとNext.jsを活用してMarkdownブログを構築する方法を紹介しました。プロジェクトのセットアップからMarkdownファイルの管理、動的ルーティングの実装、デザインの最適化、そしてデプロイまでの手順を順を追って解説しました。

Markdownを使うことで記事管理が簡単になり、Next.jsの動的ルーティングや静的サイト生成を活用することで、高速でSEOにも強いブログを構築できます。また、Tailwind CSSを利用して美しくレスポンシブなデザインを実現し、Vercelでの簡単なデプロイにより、すぐにブログを公開可能です。

この記事を参考に、自分だけのカスタマイズ可能なMarkdownブログを構築し、公開してみてください。効率的なウェブ開発と管理が可能になり、ブログ運営がより楽しくなるでしょう。

コメント

コメントする

目次