WordPress開発者のためのAstro

このページ

AstroはコンテンツにフォーカスしたWebサイトを構築するためのWebフレームワークです。EmDashを使用する場合、AstroがWordPressテーマを置き換えます。テンプレート、ルーティング、レンダリングを処理します。

このガイドは、すでに理解しているWordPressの概念にマッピングすることで、Astroの基礎を教えます。

主なパラダイムシフト

デフォルトでサーバーレンダリング

PHPと同様に、AstroコードはサーバーSo実行されます。PHPとは異なり、デフォルトでゼロ JavaScriptの静的HTMLを出力します。

追加しない限りゼロJS

WordPressは自動的にjQueryとテーマスクリプトをロードします。Astroは明示的に 追加しない限り、ブラウザに何も送信しません。

コンポーネントベースのアーキテクチャ

散在するテンプレートタグやincludeの代わりに、組み立て可能で自己完結型の コンポーネントで構築します。

ファイルベースのルーティング

リライトルールやquery_varsは不要です。src/pages/のファイル構造がURLを直接定義します。

プロジェクト構造

WordPressテーマはマジックファイル名を持つフラットな構造を持っています。Astroは明示的なディレクトリを使用します:

WordPressAstro目的
index.php, single.phpsrc/pages/ルート(URL)
template-parts/src/components/再利用可能なUIパーツ
header.php + footer.phpsrc/layouts/ページラッパー
style.csssrc/styles/グローバルCSS
functions.phpastro.config.mjsサイト設定

以下のツリーは、典型的なAstroプロジェクトのレイアウトを示しています:

src/
├── components/        # Reusable UI (Header, PostCard, etc.)
├── layouts/           # Page shells (Base.astro)
├── pages/             # Routes - files become URLs
│   ├── index.astro    # → /
│   ├── posts/
│   │   ├── index.astro      # → /posts
│   │   └── [slug].astro     # → /posts/hello-world
│   └── [slug].astro   # → /about, /contact, etc.
└── styles/
    └── global.css

Astroコンポーネント

.astroファイルはPHPテンプレートに相当するAstroのものです。各ファイルには2つのパーツがあります:

  1. フロントマター---フェンスの間)— テンプレートの最初のPHPのような、サーバーサイドコード
  2. テンプレート — PHPテンプレートの残りのような、式を持つHTML

以下のコンポーネントは、フロントマターで型付きpropsを宣言し、テンプレートでそれらをレンダリングします:

---
// Frontmatter: runs on server, never sent to browser
interface Props {
  title: string;
  excerpt: string;
  url: string;
}

const { title, excerpt, url } = Astro.props;
---
<!-- Template: outputs HTML -->
<article class="post-card">
  <h2><a href={url}>{title}</a></h2>
  <p>{excerpt}</p>
</article>

PHPからの主な違い:

  • フロントマターは分離されています。 そこで宣言された変数はテンプレートで利用可能ですが、コード自体はブラウザに到達しません。
  • インポートはフロントマターに入ります。 コンポーネント、データ、ユーティリティ — すべて上部でインポートされます。
  • TypeScriptが機能します。 エディターのオートコンプリートと検証のためにinterface Propsでprop型を定義します。

テンプレート式

Astroテンプレートは<?php ?>タグの代わりに{波括弧}を使用します。構文はJSXに似ていますが、純粋なHTMLを出力します。

Astro

---
import { getEmDashCollection } from "emdash";

const { entries: posts } = await getEmDashCollection("posts");
const showTitle = true;
---
{showTitle && <h1>Latest Posts</h1>}

{posts.length > 0 ? (
  <ul>
    {posts.map(post => (
      <li>
        <a href={`/posts/${post.id}`}>{post.data.title}</a>
      </li>
    ))}
  </ul>
) : (
  <p>No posts found.</p>
)}

PHP

<?php
$posts = new WP_Query(['post_type' => 'post']);
$show_title = true;
?>

<?php if ($show_title): ?>
  <h1>Latest Posts</h1>
<?php endif; ?>

<?php if ($posts->have_posts()): ?>
  <ul>
    <?php while ($posts->have_posts()): $posts->the_post(); ?>
      <li>
        <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
      </li>
    <?php endwhile; wp_reset_postdata(); ?>
  </ul>
<?php else: ?>
  <p>No posts found.</p>
<?php endif; ?>

式のパターン

パターン目的
{variable}値を出力
{condition && <Element />}条件付きレンダリング
{condition ? <A /> : <B />}If/else
{items.map(item => <Li>{item}</Li>)}ループ

PropsとSlots

コンポーネントはprops(関数引数のような)とslotsdo_action挿入ポイントのような)を通じてデータを受け取ります。

Astro

---
interface Props {
  title: string;
  featured?: boolean;
}

const { title, featured = false } = Astro.props;
---
<article class:list={["card", { featured }]}>
  <h2>{title}</h2>
  <slot />
  <slot name="footer" />
</article>

以下のマークアップはそのコンポーネントを使用し、デフォルトスロットと名前付きfooterスロットを渡します:

<Card title="Hello" featured>
  <p>This goes in the default slot.</p>
  <footer slot="footer">Footer content</footer>
</Card>

PHP

<?php
// Usage: get_template_part('template-parts/card', null, [
//   'title' => 'Hello',
//   'featured' => true
// ]);

$title = $args['title'] ?? '';
$featured = $args['featured'] ?? false;
$class = $featured ? 'card featured' : 'card';
?>
<article class="<?php echo esc_attr($class); ?>">
  <h2><?php echo esc_html($title); ?></h2>
  <?php
  // No direct equivalent to slots.
  // WordPress uses do_action() for similar patterns:
  do_action('card_content');
  do_action('card_footer');
  ?>
</article>

Props vs $args

WordPressでは、get_template_part()$args配列を介してデータを渡します。Astro propsは型付けされ、分割代入されます:

---
// Type-safe with defaults
interface Props {
  title: string;
  count?: number;
}
const { title, count = 10 } = Astro.props;
---

Slots vs Hooks

WordPressは挿入ポイントを作成するためにdo_action()を使用します。Astroはslotsを使用します:

WordPressAstro
do_action('before_content')<slot name="before" />
デフォルトコンテンツエリア<slot />
do_action('after_content')<slot name="after" />

違い:slotsは呼び出しサイトで子要素を受け取りますが、WordPressフックは別の場所で別のadd_action()呼び出しが必要です。

レイアウト

レイアウトは共通のHTML構造でページをラップします — <head>、ヘッダー、フッター、ページ間で共有されるすべてのもの。これはheader.php + footer.phpを置き換えます。以下のレイアウトは、その共有シェルを定義し、ページコンテンツのスロットを公開します:

---
import "../styles/global.css";

interface Props {
  title: string;
  description?: string;
}

const { title, description = "My EmDash Site" } = Astro.props;
---
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content={description} />
    <title>{title}</title>
  </head>
  <body>
    <header>
      <nav><!-- Navigation --></nav>
    </header>

    <main>
      <slot />
    </main>

    <footer>
      <p>&copy; {new Date().getFullYear()}</p>
    </footer>
  </body>
</html>

ページでレイアウトを使用します:

---
import Base from "../layouts/Base.astro";
---
<Base title="Home">
  <h1>Welcome</h1>
  <p>Page content goes in the slot.</p>
</Base>

スタイリング

Astroはいくつかのスタイリングアプローチを提供します。最も特徴的なのはスコープスタイルです。

スコープスタイル

<style>タグ内のスタイルは自動的にそのコンポーネントにスコープされます:

<article class="card">
  <h2>Title</h2>
</article>

<style>
  /* Only affects .card in THIS component */
  .card {
    padding: 1rem;
    border: 1px solid #ddd;
  }

  h2 {
    color: navy;
  }
</style>

生成されたHTMLには、スタイルの漏れを防ぐために一意のクラス名が含まれているため、セレクタの詳細度を上げることなく、コンポーネントスタイルが含まれたままになります。

グローバルスタイル

サイト全体のスタイルには、CSSファイルを作成してレイアウトにインポートします:

---
import "../styles/global.css";
---

条件付きクラス

class:listディレクティブは手動でのクラス文字列の構築を置き換えます:

Astro

---
const { featured, size = "medium" } = Astro.props;
---
<article class:list={[
  "card",
  size,
  { featured, "has-border": true }
]}>

出力:<article class="card medium featured has-border">

PHP

<?php
$classes = ['card', $size];
if ($featured) $classes[] = 'featured';
if (true) $classes[] = 'has-border';
?>
<article class="<?php echo esc_attr(implode(' ', $classes)); ?>">

クライアントサイドJavaScript

Astroはデフォルトでゼロのjavascriptを送信します。これがWordPressからの最大のメンタルシフトです。

インタラクティビティの追加

シンプルなインタラクションには、<script>タグを追加します:

<button id="menu-toggle">Menu</button>
<nav id="mobile-menu" hidden>
  <slot />
</nav>

<script>
  const toggle = document.getElementById("menu-toggle");
  const menu = document.getElementById("mobile-menu");

  toggle?.addEventListener("click", () => {
    menu?.toggleAttribute("hidden");
  });
</script>

スクリプトは自動的にバンドルされ、重複排除されます。このコンポーネントがページに2回表示される場合、スクリプトは1回実行されます。

高度なインタラクティブコンポーネント

より複雑なインタラクティビティのために、AstroはオンデマンドでJavaScriptコンポーネント(React、Vue、Svelte)をロードできます。これはオプションです — ほとんどのサイトは<script>タグだけでうまく機能します。以下のページは、ビューにスクロールしたときにのみコンポーネントをロードします:

---
import SearchWidget from "../components/SearchWidget.jsx";
---
<!-- Only load JavaScript when the search box scrolls into view -->
<SearchWidget client:visible />
ディレクティブJavaScriptがロードされるタイミング
client:loadページロード時に即座に
client:visibleコンポーネントがビューポートに入ったとき
client:idleブラウザがアイドル状態のとき

ルーティング

Astroはファイルベースのルーティングを使用します。src/pages/のファイルがURLになります:

ファイルURL
src/pages/index.astro/
src/pages/about.astro/about
src/pages/posts/index.astro/posts
src/pages/posts/[slug].astro/posts/hello-world
src/pages/[...slug].astro任意のパス(キャッチオール)

動的ルート

CMSコンテンツの場合、動的セグメントにブラケット構文を使用します:

---
import { getEmDashCollection, getEmDashEntry } from "emdash";
import Base from "../../layouts/Base.astro";
import { PortableText } from "emdash/ui";

// For static builds, define which pages to generate
export async function getStaticPaths() {
  const { entries: posts } = await getEmDashCollection("posts");
  return posts.map(post => ({
    params: { slug: post.id },
    props: { post },
  }));
}

const { post } = Astro.props;
---
<Base title={post.data.title}>
  <article>
    <h1>{post.data.title}</h1>
    <PortableText value={post.data.content} />
  </article>
</Base>

WordPressとの比較

WordPressAstro
テンプレート階層(single-post.php明示的なファイル:posts/[slug].astro
リライトルール + query_varsファイル構造
$wp_queryがテンプレートを決定URLがファイルに直接マップ
add_rewrite_rule()ファイルまたはフォルダーを作成

WordPressの概念がどこに存在するか

WordPress機能のAstro/EmDash相当を見つけるためのリファレンス:

テンプレーティング

WordPressAstro/EmDash
テンプレート階層src/pages/でのファイルベースルーティング
get_template_part()コンポーネントをインポートして使用
the_content()<PortableText value={content} />
the_title(), the_*()post.data.title経由でアクセス
テンプレートタグテンプレート式{value}
body_class()class:listディレクティブ

データとクエリ

WordPressAstro/EmDash
WP_QuerygetEmDashCollection(type, filters)
get_post()getEmDashEntry(type, id)
get_posts()getEmDashCollection(type)
get_the_terms()entry.data.categories経由でアクセス
get_post_meta()entry.data.fieldName経由でアクセス
get_option()getSiteSettings()
wp_nav_menu()getMenu(location)

拡張性

WordPressAstro/EmDash
add_action()EmDashフック、Astroミドルウェア
add_filter()EmDashフック
add_shortcode()Portable Textカスタムブロック
register_block_type()Portable Textカスタムブロック
register_sidebar()EmDashウィジェットエリア
プラグインAstro統合 + EmDashプラグイン

コンテンツタイプ

WordPressAstro/EmDash
register_post_type()管理UIでコレクションを作成
register_taxonomy()管理UIでタクソノミーを作成
register_meta()コレクションスキーマにフィールドを追加
投稿ステータスエントリーステータス(draft、published等)
アイキャッチ画像メディア参照フィールド
GutenbergブロックPortable Textブロック

概念のマッピング

このガイドでカバーされている主なWordPressからAstroへのシフト:

  • PHPテンプレートはAstroコンポーネントになります:明示的なファイル編成を伴うサーバーコードとHTML。
  • テンプレートタグはpropsとimportになります:データはグローバルの代わりに引数を通じて流れます。
  • テーマファイルはpagesディレクトリになります:URLはファイル構造と一致します。
  • フックはslotsとミドルウェアになります:挿入ポイントはコンテンツが渡される場所で定義されます。
  • jQueryはWordPressではデフォルトでロードされます;Astroは追加するまでJavaScriptを送信しません。

最初のEmDashサイトを構築するにはGetting Startedガイドから始めるか、Working with Contentを探索してCMSデータをクエリしてレンダリングする方法を学びます。