フードブログをWordPressで運営しているなら、すでに流れは理解しているでしょう。MediavineやAdThriveの広告、WP Recipe MakerやTasty Recipesなどのレシピカードプラグイン、おそらく構造化データを持つ800以上の投稿があり、キャッシングプラグインを最善を尽くして使用しているにもかかわらずモバイルPageSpeed Insightsで34点のサイトを持っています。「画像を最適化するだけ」とだいたい50回は言われてきたでしょう。一方、Core Web Vitalsが検索ランキングを低下させており、新しいプラグイン更新のたびにレイアウトに対するロシアンルーレットのように感じます。

ここ2年間、私はいくつかのレシピブログをWordPressからNext.jsに移行してきましたが、結果は一貫して劇的です:ページ読み込みが2~3倍高速化し、Lighthouseスコアが完璧になり、最も重要なことに、Googleが高速化を報酬するため実際に成長するトラフィックが得られます。しかし、移行は簡単ではありません。レシピブログには、標準的なWordPressからNext.jsへの移行ガイドではカバーされない固有の課題があります。この記事では、データ抽出からレシピスキーマから広告統合まで、プロセス全体を説明しています。

目次

WordPressレシピブログをNext.jsに移行する:実践ガイド

フードブロガーがWordPressを離れている理由

ここで正直に言いましょう。WordPress自体は問題ではなく、WordPressでのレシピブログが何になっているかが問題です。典型的なフードブログのWordPressインストレーションは次のようになります:

  • プレミアムテーマ(多くの場合Flavor、Flavor Pro、またはFlavorベースの子テーマ)
  • レシピカード用のWP Recipe MakerまたはTasty Recipes
  • 広告管理プラグイン(またはMediavine/AdThrive スクリプトインジェクション)
  • キャッシングプラグイン(WP Rocket、W3 Total Cache、またはLiteSpeed)
  • 画像最適化プラグイン(ShortPixel、Imagify、またはEWWW)
  • Yoast SEOまたはRank Math
  • ソーシャルシェアリングプラグイン
  • メールオプトインプラグイン
  • レシピへジャンプボタンプラグイン
  • プリント機能レシピプラグイン

これは書き始める前にすでに10以上のプラグインです。各プラグインはJavaScript、CSS、データベースクエリ、潜在的な競合を追加します。その結果?3~4 MBのアセットを読み込み、モバイルで6~8秒かかってインタラクティブになるページです。

Googleは2024年のコアアップデート以来、ページエクスペリエンスがこれ以上に重要であることを明確にしています。レシピ検索は非常に競争的です。数百の他のブログに対してフィーチャースニペットとレシピカルーセルと競争しています。サイトが遅い場合、負けます。

プラグイン依存の実際のコスト

ここで十分に議論されていないことがあります:レシピデータ形式を所有していません。WP Recipe Makerを使用すると、レシピはそのプラグインに固有のカスタムポストタイプとカスタムフィールドに保存されます。プラグインが放棄された場合、取得された場合、または重大な変更があった場合、動けなくなります。これが起きたのを見てきました。Tasty RecipesはWP Tastyに買収され、価格が変わり、機能がシフトしました。コンテンツは他の人のデータ構造の中に閉じ込められています。

ヘッドレスアプローチでは、レシピデータは構造化された、ポータブルな、管理可能な形式で存在します。

実際に移行するもの

コードに触れる前に、インベントリが必要です。レシピブログの移行は、関連するデータの理由により、標準的なブログ移行より複雑です:

コンテンツタイプ WordPressソース 移行の複雑性
ブログ投稿(ナラティブ) wp_posts 低
レシピデータ(材料、ステップ、時間) プラグインカスタムフィールド 高
レシピ画像(ヒーロー、ステップバイステップ) wp_uploads + postmeta 中
構造化データ(JSON-LD) プラグイン生成 高(再構築が必要)
カテゴリー/タグ wp_terms 低
コメント wp_comments 中
内部リンク 投稿コンテンツ 中
URLスラッグ パーマリンク 重要
広告配置 プラグイン/テーマフック 中
メールサインアップフォーム プラグインショートコード 低

レシピデータが難しい部分です。他のすべては標準的なWordPress移行分野です。

アーキテクチャの選択

ここではいくつかのパスがあり、正しいパスはあなたの技術的快適さと予算に依存します。

オプションA:Next.js + ヘッドレスWordPress

WordPressをCMSとして保持しますが、REST APIまたはWPGraphQL経由のコンテンツバックエンドとして純粋に使用します。Next.jsフロントエンドはビルド時またはリクエスト時にWordPressからデータを取得します。

長所: WordPressエディタを保持します。ライターは何も新しく学ぶ必要がありません。WP Recipe MakerデータはAPI経由でアクセス可能です。

短所: WordPressインストレーションを引き続き維持する必要があります。それをホストするために支払い続けます。REST APIは複雑なレシピクエリで遅い可能性があります。

オプションB:Next.js + モダンヘッドレスCMS

WordPressからすべてをエクスポートし、Sanity、Contentful、またはPayload CMSなどの目的に応じたヘッドレスCMSに移行します。Next.jsでフロントエンドを構築します。

長所: クリーンな切り分け。レシピのより良いコンテンツモデリング。WordPressメンテナンスなし。より高速なAPI応答。

短所: より大きな初期移行作業。コンテンツエディタは新しいCMSを学ぶ必要があります。CMS選択によってコスト変動。

オプションC:Next.js + Markdown/MDX

より小さいブログ(200投稿未満)では、すべてをMDXファイルにエクスポートして完全に静的にすることができます。

長所: CMSコストなし。超高速。すべてがバージョン管理中。

短所: スケーリングが悪い。技術的でないエディタは使用できません。リアルタイムプレビューなし。

200以上のレシピを持つほとんどのフードブロガーに対して、私はオプションB SanityをCMSとして推奨します。コンテンツモデリングの柔軟性はレシピに最適で、編集エクスペリエンスは非開発者にとって優れており、価格は合理的です(無料ティアはほとんどのフードブログをカバーしています)。我々はこのセットアップのいくつかをヘッドレスCMS開発作業を通じて構築してきており、結果は自分たちのために語っています。

WordPressレシピブログをNext.jsに移行する:実践ガイド - アーキテクチャ

WordPressからレシピデータを抽出

ここから興味深くなります。レシピプラグインはデータを異なる方法で保存するため、正確に何を扱っているかを知る必要があります。

WP Recipe Maker エクスポート

WP Recipe Makerはレシピをカスタムポストタイプ(wprm_recipe)として、wp_postmetaのデータで保存します。経由でエクスポートできます:

  1. WP Recipe Makerの組み込みエクスポート -- JSONファイルを提供しますが、それらの独自形式です
  2. WPGraphQL + WP Recipe Maker拡張 -- GraphQL経由でレシピデータをクエリ
  3. 直接データベースエクスポート -- データベースを直接クエリするカスタムスクリプトを記述

WP Recipe Maker JSONエクスポートをクリーンな形式に変換するために使用するNode.jsスクリプトは次のとおりです:

const fs = require('fs');
const wprmData = JSON.parse(fs.readFileSync('./wprm-export.json', 'utf8'));

const recipes = wprmData.map((recipe) => ({
  title: recipe.name,
  slug: recipe.slug,
  summary: recipe.summary,
  prepTime: recipe.prep_time, // 分単位
  cookTime: recipe.cook_time,
  totalTime: recipe.total_time,
  servings: recipe.servings,
  servingsUnit: recipe.servings_unit,
  ingredients: recipe.ingredients.map((group) => ({
    groupName: group.name || 'Main',
    items: group.ingredients.map((ing) => ({
      amount: ing.amount,
      unit: ing.unit,
      name: ing.name,
      notes: ing.notes,
    })),
  })),
  instructions: recipe.instructions.map((group) => ({
    groupName: group.name || 'Instructions',
    steps: group.instructions.map((step) => ({
      text: step.text,
      image: step.image ? extractImageUrl(step.image) : null,
    })),
  })),
  nutrition: recipe.nutrition,
  notes: recipe.notes,
  video: recipe.video,
}));

fs.writeFileSync(
  './recipes-clean.json',
  JSON.stringify(recipes, null, 2)
);

Tasty Recipes エクスポート

Tasty Recipesは異なる方法でデータを保存します。postmetaではなくカスタムテーブル(wp_tasty_recipes)を使用します。直接データベースアクセスが必要になります:

SELECT
  r.id,
  r.post_id,
  r.title,
  r.description,
  r.prep_time,
  r.cook_time,
  r.total_time,
  r.yield,
  r.ingredients,
  r.instructions,
  r.notes,
  r.nutrition
FROM wp_tasty_recipes r
JOIN wp_posts p ON r.post_id = p.ID
WHERE p.post_status = 'publish';

ingredientsとinstructionsフィールドはHTMLストリングとして保存されているため、構造化データに解析する必要があります。このためにcheerioを使用します:

const cheerio = require('cheerio');

function parseIngredients(html) {
  const $ = cheerio.load(html);
  const groups = [];
  let currentGroup = { name: 'Main', items: [] };

  $('li, h4, strong').each((_, el) => {
    if (el.tagName === 'h4' || (el.tagName === 'strong' && $(el).parent().is('p'))) {
      if (currentGroup.items.length > 0) groups.push(currentGroup);
      currentGroup = { name: $(el).text().trim(), items: [] };
    } else if (el.tagName === 'li') {
      currentGroup.items.push(parseIngredientLine($(el).text().trim()));
    }
  });

  if (currentGroup.items.length > 0) groups.push(currentGroup);
  return groups;
}

Next.jsレシピブログのセットアップ

Next.js 15(2026年現在の現在の安定版リリース)では、レンダリング戦略に優れたオプションがあります。レシピブログの場合、ハイブリッドアプローチをお勧めします:

  • 静的生成(SSG) すべてのレシピページの場合 -- 頻繁に変わりません
  • ISR(増分静的再生成) 1時間の再検証によるカテゴリー/タグページ
  • サーバーコンポーネント レイアウトとナビゲーション
npx create-next-app@latest my-recipe-blog --typescript --tailwind --app

ここに基本的なレシピページ構造があります:

// app/recipes/[slug]/page.tsx
import { getRecipeBySlug, getAllRecipeSlugs } from '@/lib/recipes';
import { RecipeCard } from '@/components/RecipeCard';
import { RecipeJsonLd } from '@/components/RecipeJsonLd';
import { notFound } from 'next/navigation';

export async function generateStaticParams() {
  const slugs = await getAllRecipeSlugs();
  return slugs.map((slug) => ({ slug }));
}

export async function generateMetadata({ params }: { params: { slug: string } }) {
  const recipe = await getRecipeBySlug(params.slug);
  if (!recipe) return {};

  return {
    title: `${recipe.title} | My Recipe Blog`,
    description: recipe.summary.slice(0, 155),
    openGraph: {
      images: [{ url: recipe.heroImage.url, width: 1200, height: 630 }],
    },
  };
}

export default async function RecipePage({ params }: { params: { slug: string } }) {
  const recipe = await getRecipeBySlug(params.slug);
  if (!recipe) notFound();

  return (
    <article>
      <RecipeJsonLd recipe={recipe} />
      {/* ナラティブコンテンツ(ブログ投稿部分) */}
      <div className="prose lg:prose-xl" dangerouslySetInnerHTML={{ __html: recipe.narrativeContent }} />
      {/* 実際のレシピカード */}
      <RecipeCard recipe={recipe} />
    </article>
  );
}

Next.js開発が初めての場合、またはプロフェッショナルな移行のサポートが必要な場合は、Next.js開発機能をご確認ください。

構造化データを使用したレシピコンポーネントの構築

構造化データはレシピブログにとって非交渉です。有効なRecipeスキーママークアップがなければ、Googleのレシピカルーセル、リッチスニペット、またはGoogle Discoverに表示されません。これはここで多くの移行が間違う場所です -- WP Recipe Makerが自動的に生成していた構造化データを再構築するのを忘れます。

レシピの有効なJSON-LDを生成するコンポーネントはここにあります:

// components/RecipeJsonLd.tsx
import type { Recipe } from '@/types/recipe';

export function RecipeJsonLd({ recipe }: { recipe: Recipe }) {
  const jsonLd = {
    '@context': 'https://schema.org/',
    '@type': 'Recipe',
    name: recipe.title,
    image: recipe.images.map((img) => img.url),
    author: {
      '@type': 'Person',
      name: recipe.author.name,
    },
    datePublished: recipe.publishedAt,
    description: recipe.summary,
    prepTime: `PT${recipe.prepTime}M`,
    cookTime: `PT${recipe.cookTime}M`,
    totalTime: `PT${recipe.totalTime}M`,
    recipeYield: `${recipe.servings} ${recipe.servingsUnit}`,
    recipeCategory: recipe.category,
    recipeCuisine: recipe.cuisine,
    recipeIngredient: recipe.ingredients.flatMap((group) =>
      group.items.map((ing) =>
        `${ing.amount} ${ing.unit} ${ing.name}${ing.notes ? ` (${ing.notes})` : ''}`
      )
    ),
    recipeInstructions: recipe.instructions.flatMap((group) =>
      group.steps.map((step, i) => ({
        '@type': 'HowToStep',
        name: `Step ${i + 1}`,
        text: step.text,
        ...(step.image && { image: step.image.url }),
      }))
    ),
    ...(recipe.nutrition && {
      nutrition: {
        '@type': 'NutritionInformation',
        calories: recipe.nutrition.calories,
        fatContent: recipe.nutrition.fat,
        proteinContent: recipe.nutrition.protein,
        carbohydrateContent: recipe.nutrition.carbs,
      },
    }),
    ...(recipe.video && {
      video: {
        '@type': 'VideoObject',
        name: recipe.video.title,
        description: recipe.video.description,
        thumbnailUrl: recipe.video.thumbnail,
        contentUrl: recipe.video.url,
        uploadDate: recipe.video.uploadDate,
      },
    }),
  };

  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
    />
  );
}

変更のたびにGoogleのリッチ結果テストで構造化データを検証してください。正しく見えるために正しいと仮定しないでください。

画像とメディアの処理

フードブログは画像が多いです。単一のレシピ投稿には15~25枚の画像がある場合があります。これは実際にはNext.jsが最も輝く場所です -- 組み込みのnext/imageコンポーネントは、応答性のあるサイズ変更、形式変換(WebP/AVIF)、遅延読み込みを自動的に処理します。

しかし、既存の画像のための戦略が必要です:

  1. wp-content/uploads/からすべての画像をエクスポート -- 通常は年/月で整理されています
  2. CDNまたはクラウドストレージにアップロード -- Cloudinary、Vercel Blob Storage、またはAWS S3 + CloudFront
  3. コンテンツ内のすべての画像参照を更新 新しいURLを指す

フードブログにはCloudinaryを強く推奨します。変換APIにより、その場で最適化された画像を提供でき、無料ティアが太っ腹です(月25クレジット、ほとんどのフードブログをカバー)。さらに、自動トリミングは食べ物を中央に保つのに十分にスマートです -- あなたが思うより重要です。

// lib/cloudinary.ts
export function getRecipeImageUrl(
  publicId: string,
  width: number = 800,
  height: number = 600
) {
  return `https://res.cloudinary.com/${process.env.CLOUDINARY_CLOUD}/image/upload/c_fill,w_${width},h_${height},f_auto,q_auto/${publicId}`;
}

SEO移行チェックリスト

これはフードブロガーが夜中に起きている理由であり、それは正当です。台無しの移行は何ヶ月間有機トラフィックを低下させることができます。このチェックリストに宗教的に従ってください:

タスク 優先度 詳細
URLマッピング 重要 古いURLから新しいURLへの完全な1対1マップを作成
301リダイレクト 重要 すべての古いURLをリダイレクト。すべて。1つも漏らさず。
XMLサイトマップ 重要 生成し、Google Search Consoleに送信
構造化データ検証 重要 リッチ結果テストで各レシピページをテスト
正規タグ 高 すべてのページに自己参照正規タグがあることを確認
内部リンク監査 高 投稿コンテンツ内のすべての内部リンクを更新
画像代替テキスト 高 移行中にすべての既存代替テキストを保持
メタディスクリプション 中 既存のメタディスクリプションを移行または改善
robots.txt 中 更新して検証
ソーシャルメタタグ 中 OpenGraphとTwitterカード(各レシピ)
Google Search Console 高 新しいプロパティを検証、サイトマップを送信、監視
アナリティクス 高 GA4をセットアップし、適切なイベント追跡

URLの問題

WordPressフードブログは通常/recipe-name/または/category/recipe-name/のような構造を使用します。現在の構造が何であれ、保持してください。移行中にURLパターンを変更して賢いことをしないでください。現在のURLがexample.com/easy-chicken-tikka-masala/のように見える場合、新しいNext.js URLは同じである必要があります。

next.config.jsで、変更する必要があるURLのリダイレクトをセットアップします:

// next.config.js
module.exports = {
  async redirects() {
    return [
      // 例:カテゴリーページURL変更
      {
        source: '/category/:slug',
        destination: '/recipes/:slug',
        permanent: true,
      },
      // WordPressページネーション
      {
        source: '/page/:num',
        destination: '/?page=:num',
        permanent: true,
      },
    ];
  },
};

広告ネットワーク統合

お話しましょう象のような話。ほとんどのフードブロガーはMediavine、Raptive(以前はAdThrive)、または同様のネットワークからの広告を通じてお金を稼いでいます。これらの広告ネットワークはWordPressのために設計されており、JavaScriptフレームワークへの移行は複雑さを追加します。

Next.jsでのMediavine

Mediavineはユニバーサルプレーヤーをリリースし、非WordPressサイトをサポートしていますが、以下をする必要があります:

  1. 移行前にMediavineの担当者に連絡 をして知らせます
  2. Mediavineスクリプトラッパーをapp/layout.tsxに追加
  3. 要件を尊重する広告配置コンポーネントを作成
  4. ステージング環境で十分にテスト
// components/AdPlacement.tsx
'use client';

import { useEffect, useRef } from 'react';

export function AdPlacement({ id }: { id: string }) {
  const adRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    // Mediavineはこれらのdivを動的に埋めます
    if (window.__mediavine_ad_settings) {
      window.__mediavine_ad_settings.refreshAd(id);
    }
  }, [id]);

  return <div ref={adRef} id={id} data-mediavine-ad="" />;
}

重要: 広告ネットワークに相談してください。SPA(シングルページアプリケーション)に対して特定の技術要件がある場合があります。Mediavineのチームは私の経験から役に立つことが多くありますが、何をしているかを伝える必要があります。

Raptive(AdThrive)に関する考慮事項

Raptiveはヘッドレスセットアップの採用が遅かった。2026年初め時点で、彼らはカスタム実装をサポートしていますが、技術レビューが必要です。承認プロセスに2~4週間を予算に入れてください。

パフォーマンスベンチマーク:移行前後

2025年から2026年の間に実行した3つのレシピブログ移行からの実データはここにあります:

メトリック WordPress(平均) Next.js(平均) 改善
Lighthouseパフォーマンス(モバイル) 31 94 +203%
最大な描画ペイント 4.8秒 1.2秒 -75%
合計ブロッキング時間 1,850ms 45ms -97%
累積レイアウトシフト 0.35 0.02 -94%
ページ重量 3.8 MB 420 KB -89%
インタラクティブまでの時間 8.2秒 1.8秒 -78%
Core Web Vitals合格率 ページの22% ページの98% +345%

これらの数字は厳選されていません。400~1200の発行レシピを持つブログ間の平均です。Mediavineの両バージョンで広告を実行しています。Next.jsバージョンはVercelにデプロイされました。

トラフィック影響?1つのブログは移行後3ヶ月以内に有機検索トラフィックで47%の増加を見ました。主に改善されたレシピカルーセルの外観とより良いモバイルランキングから。

レシピコンテンツ用のヘッドレスCMSの選択

ヘッドレスCMSルート(前述のオプションB)に行く場合、CMSの選択は特にレシピコンテンツで重要です。

CMS レシピコンテンツモデリング エディタエクスペリエンス 価格(2026) 最適な用途
Sanity 優れた(カスタムスキーマ) 優秀 最初の100K APIリクエストまで無料 レシピ構造を完全に制御
Contentful 優秀(構造化コンテンツタイプ) 優秀 最初の1M APIコールまで無料 確立されたワークフロー
Payload CMS 優れた(自己ホスト) 優秀 無料(オープンソース) 完全な所有権が必要な開発者
Strapi 優秀(カスタムコンテンツタイプ) まあまあ 無料(自己ホスト)/ クラウドから月29ドル 予算に配慮した移行
WordPress(ヘッドレス) 既存を継承 使い慣れた 既存ホストコスト エディタ中断最小化

レシピブログにはSanityが最適です。カスタムスキーマシステムにより、材料グループ、ステップ写真、栄養データ、機器リストを含め、必要に応じてレシピをモデル化できます。Portable Textエディタはナラティブブログ投稿コンテンツに十分柔軟で、画像パイプラインは変換をネイティブに処理します。

かなりいくつかのSanity搭載レシピサイトをセットアップしました。このルートを探索したい場合は、ヘッドレスCMS開発サービスを見るか、お問い合わせして特定の状況について議論してください。

FAQ

WordPressからNext.jsに移行したら、Googleランキングを失いますか?

正しく行った場合はそうではありません。鍵はURL平等を維持すること(同じURL)、変更する必要があるURLに対して適切な301リダイレクトを実装すること、構造化データを保持することです。Googleのジョン・ミューラーは、コンテンツとURLが同じままであれば、CMSを変更することがランキングに影響すべきではないと何度も述べています。実践では、より良いCore Web Vitalsによる改善に続く一時的な変動(1~2週間)を見てきました。

ヘッドレスWordPressセットアップでWP Recipe Makerを引き続き使用できますか?

はい。WP Recipe MakerはWordPress REST API経由でレシピデータを公開します。ポストオブジェクトの一部としてレシピフィールドにアクセスします。ただし、レシピカードを提供し、Next.js側で構造化データを生成するのはあなたの責任です -- プラグインは生のデータのみを提供し、フロントエンド出力ではありません。

WordPressからNext.jsにレシピブログを移行するのにいくらかかりますか?

複雑さに応じて非常に大きく異なります。200レシピのシンプルな設計の場合、プロフェッショナル移行で5,000~10,000ドルになる可能性があります。1000+のレシピを持つブログ、カスタム機能、広告統合、複雑な設計は15,000~30,000ドル以上で実行できます。価格ページを確認してください。DIYは技術的な場合は可能ですが、2~4ヶ月のパートタイム作業を予算に入れてください。

WordPressのコメントはどうですか?那些を移行できますか?

できます。REST APIまたはWP-CLI経由でエクスポートします。ヘッドレスCMSにインポートするか、Disqus、Commento、またはGiscusなどのサードパーティコメントシステムに切り替えます。正直に言うと、ほとんどのフードブロガーは、移行を機会として使用してコメントを完全に削除するか、よりシンプルなシステムに切り替えます。レシピブログのコメントセクションは主に「Xで置き換えられますか?」で、各レシピの構造化FAQ部分でよりよく提供できます。

MediavineとRaptiveはNext.jsで機能しますか?

Mediavineは非WordPressサイトを公式にサポートしており、JavaScriptフレームワーク統合のドキュメントがあります。Raptiveはカスタム実装をサポートしていますが、技術レビューが必要です。両者ともカスタム統合作業が必要です -- プラグインをインストールできません。移行を開始する前に広告ネットワークの担当者に相談してください。そのため、彼らは要件について案内できます。

Next.jsまたはAstroを使用すべきですか?

どちらも素晴らしい選択です。Astroは、ほとんどのインタラクティビティが必要ないコンテンツが多いサイトの場合、おそらくより適切です -- デフォルトではゼロJavaScriptを出荷します。Next.jsはインタラクティブ機能(レシピスケーリング、ユニット変換、ショッピングリスト生成)にさらに柔軟性を与え、より大きなエコシステムがあります。ブログが主に静的コンテンツとレシピの場合、Astroは検討する価値があります。また、Astro開発も提供しています。

プラグインなしでレシピ印刷機能をどのように処理しますか?

印刷スタイルシートと印刷固有のコンポーネントを構築します。Next.jsでは実際にはシンプルです。なぜなら、マークアップを完全に制御しているからです。@media printCSSルールを使用してナビゲーション、広告、ナラティブコンテンツを非表示にし、レシピカードのみを表示します。レシピカードのみをレンダリングする専用/recipes/[slug]/printルートを作成することもできます。

レシピスケーリングとユニット変換機能は何ですか?

これはNext.jsが実際にWordPressと比較して輝く場所です。サービング選択に基づいて基本材料額を乗算するクライアントコンポーネントを構築します。ユニット変換(US~メトリック)の場合、一般的な調理測定をマップするユーティリティ関数を作成します。これらのインタラクティブ機能はReactでは些細ですが、WordPressで重いjQueryプラグインが必要でした。材料額を構造化データ(別のamount、unit、nameフィールド)として保存します。プレーンテキスト文字列ではなく -- これにより、プログラム的操作が可能になります。