ブログコンテンツの移行:ContentfulからNext.jsの静的Markdownへ

August 12, 2025 開発ノート Next.js Contentful Markdown データ移行

Development Image

ContentfulのようなヘッドレスCMSからNext.jsプロジェクトの静的Markdownファイルへブログコンテンツを移行することは、デプロイの簡素化や外部依存関係の削減といった利点をもたらします。この投稿では、Contentfulからデータを抽出し、静的Markdown形式に変換するプロセスを詳しく説明します。

Contentfulのデータ構造を理解する

移行の前に、Contentfulでブログデータがどのように構造化されているかを理解することが重要です。主要なフィールドには通常、以下が含まれます。

Contentfulからデータを取得する

Contentfulは、コンテンツを取得するためのContent Delivery APIを提供しています。Space IDとAccess Tokenが必要です。

GET https://cdn.contentful.com/spaces/{SPACE_ID}/environments/master/entries?access_token={ACCESS_TOKEN}&content_type=pageBlogPost&order=-fields.publishedDate&select=fields.title,fields.publishedDate,fields.slug,fields.shortDescription,fields.content,fields.tags

コンテンツに関する重要な注意点: Contentfulのリッチテキストフィールドは、プレーンなMarkdownやHTMLではなく、特定のJSON形式でコンテンツを返します。contentフィールドがプレーンテキストの場合、埋め込み画像や複雑な書式設定が含まれていない可能性があります。リッチテキストの場合、通常はHTMLやMarkdownに変換するためにライブラリ(例:@contentful/rich-text-html-renderer)が必要になります。私たちの場合、contentフィールドはプレーンテキストであったため、変換が簡素化されました。

Markdown形式への変換

各Contentfulエントリは、YAMLフロントマターを持つMarkdownファイルに変換する必要があります。

フロントマターの構造: フロントマターは、Markdownファイルの先頭にあるYAMLブロックで、メタデータを含みます。

title: "あなたの投稿タイトル"
date: "YYYY-MM-DD"
description: "あなたの投稿の簡単な説明。"
tags: ["タグ1", "タグ2"]
---

コンテンツ本文: 投稿の本文はフロントマターの後に続きます。Contentfulのコンテンツがすでにプレーンテキストであれば、そのまま使用できます。適切な改行が維持されていることを確認してください。

移行の自動化

Node.jsスクリプトでこのプロセスを自動化できます。

  1. Contentfulから関連するすべてのエントリを取得します。
  2. 各エントリを反復処理します。
    • フロントマターのデータを抽出します。
    • ファイル名にはslugを使用します。
    • Markdownファイルの内容(フロントマター+本文)を構築します。
    • 目的のディレクトリ(例:src/app/blog/en/)にファイルを書き込みます。

スクリプトの例(概念):

const fs = require('fs');
const path = require('path');
// ... (Contentfulデータ配列) ...

posts.forEach(post => {
  const frontMatter = `---
title: ${JSON.stringify(post.frontMatter.title)}
date: ${post.frontMatter.date}
description: ${JSON.stringify(post.frontMatter.description)}
tags: [${post.frontMatter.tags.map(tag => JSON.stringify(tag)).join(', ')}]
---
`;

  const markdownContent = `${frontMatter}

${post.content}`;
  const filePath = path.join(postsDirectory, post.lang, `${post.slug}.md`);
  fs.writeFileSync(filePath, markdownContent, 'utf8');
});

画像の処理

Contentfulのリッチテキストフィールドに埋め込まれた画像は、テキストコンテンツの一部ではありません。それらは別のアセットです。

これらの手順に従うことで、ブログコンテンツを動的なCMSから静的なファイルベースのシステムに正常に移行し、Next.jsのデプロイを簡素化できます。

← Previous Entry: Next.jsブログのセットアップ:初期のGitとデプロイの課題を乗り越えるNext Entry: Cloudflare PagesでのNext.jsデプロイを極める:Edge Runtimeと静的生成の課題を克服する
← Back to Blog List