TwitterFacebookHatena

Markdown で WordPress 記事を Next.js に移行する方法

1. WordPress のデータをエクスポート

まずはじめに、WordPress の記事データをエクスポートしましょう。WordPress 管理画面の「ツール」>「エクスポート」から、すべての投稿データを XML 形式でエクスポートします。このデータを使って、後ほど Markdown 形式に変換します。

2. エクスポートしたデータを Markdown に変換

WordPress のデータをエクスポートしたら、次にそのデータを Markdown 形式に変換します。以下の TypeScript コードを用いて、XML ファイルを読み込んで Markdown に変換することができます。

import fs from 'fs'
import xml2js from 'xml2js'
import TurndownService from 'turndown'

const parser = new xml2js.Parser()
const turndownService = new TurndownService()

fs.readFile('exported-wordpress-data.xml', 'utf-8', (err, data) => {
  if (err) throw err

  parser.parseString(data, (err, result) => {
    if (err) throw err

    const posts = result.rss.channel[0].item
    posts.forEach((post) => {
      const content = post['content:encoded'][0]
      const markdown = turndownService.turndown(content)
      fs.writeFileSync(`./markdown/${post.title[0]}.md`, markdown, 'utf-8')
    })
  })
})

このコードを実行すると、エクスポートされた XML ファイルから各投稿データを抽出し、Markdown 形式に変換して、指定されたフォルダに保存されます。

3. Next.js プロジェクトで Markdown データを読み込む

次に、Next.js プロジェクトで Markdown データを読み込み、記事一覧や記事詳細ページを生成しましょう。

まずは、getPosts という関数を作成し、プロジェクト内の Markdown ファイルを読み込むようにします。

// lib/posts.ts

import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'

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

export type PostData = {
  id: string
  title: string
  date: string
  content: string
}

export function getPosts(): PostData[] {
  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 { data, content } = matter(fileContents)

    const postData: PostData = {
      id,
      title: data.title,
      date: data.date,
      content,
    }
    return postData
  })

  return allPostsData.sort((a, b) => (a.date < b.date ? 1 : -1))
}

この getPosts 関数は、Markdown ファイルからデータを取得し、PostData 型の配列を返します。

次に、記事一覧ページと記事詳細ページを作成します。

記事一覧ページ (pages/index.tsx) の作成:

import { GetStaticProps } from 'next'
import Link from 'next/link'
import { PostData, getPosts } from '../lib/posts'

type Props = {
  allPostsData: PostData[]
}

const Home = ({ allPostsData }: Props) => {
  return (
    <div>
      <h1>記事一覧</h1>
      <ul>
        {allPostsData.map(({ id, date, title }) => (
          <li key={id}>
            <Link href={`/posts/${id}`}>
              <a>{title}</a>
            </Link>
            <br />
            <small>{date}</small>
          </li>
        ))}
      </ul>
    </div>
  )
}

export const getStaticProps: GetStaticProps = async () => {
  const allPostsData = getPosts()
  return {
    props: {
      allPostsData,
    },
  }
}

export default Home

記事詳細ページ (pages/posts/[id].tsx) の作成:

import { GetStaticPaths, GetStaticProps } from 'next'
import { PostData, getPosts } from '../../lib/posts'

type Props = {
  postData: PostData
}

const Post = ({ postData }: Props) => {
  return (
    <div>
      <h1>{postData.title}</h1>
      <small>{postData.date}</small>
      <div dangerouslySetInnerHTML={{ __html: postData.content }} />
    </div>
  )
}

export const getStaticPaths: GetStaticPaths = async () => {
  const paths = getPosts().map((post) => ({
    params: { id: post.id },
  }))
  return { paths, fallback: false }
}

export const getStaticProps: GetStaticProps = async ({ params }) => {
  const postData = getPosts().find((post) => post.id === params.id)
  return { props: { postData } }
}

export default Post

これで、Next.js プロジェクトに記事一覧ページと記事詳細ページが追加されました。これらのページでは、getStaticPropsgetStaticPaths を使って、Markdown ファイルから読み込んだデータを表示します。

これで、WordPress の記事を Markdown に変更し、Next.js に乗り換える方法を実装することができました。Next.js と TypeScript を使って、簡単に WordPress の記事を移行できるようになります。

Markdown で WordPress 記事を Next.js に移行する方法