レイアウトとコンポーネント設計
Astroに入門してみる の章目次12 章
目次
#この章で学ぶこと
ここまで、各ページに <html>, <head>, <body> を繰り返し書いてきました。この章では、レイアウト を使ってページ間で共通のHTML構造を共有し、コードの重複を排除する方法を学びます。
#レイアウトとは
レイアウトは、<html>, <head>, <meta>, <nav>, <footer> といったページ共通の構造を1箇所にまとめるための特殊なコンポーネントです。Astroのレイアウトに特別な構文はなく、<slot /> を持つ通常の .astro コンポーネント です。
#ベースレイアウトの作成
最も基本的なレイアウトを作成しましょう。
---interface Props { title: string; description?: string;}
const { title, description = "Astroで作ったサイト" } = Astro.props;---
<!doctype html><html lang="ja"> <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> <nav> <a href="/">ホーム</a> <a href="/about">サイトについて</a> <a href="/blog">ブログ</a> </nav>
<main> <slot /> </main>
<footer> <p>© 2026 My Astro Site</p> </footer> </body></html>ページ側で使うときは、レイアウトをインポートして囲むだけです。
---import BaseLayout from '../layouts/BaseLayout.astro';---
<BaseLayout title="ホーム"> <h1>ようこそ!</h1> <p>Astroで構築したサイトです。</p></BaseLayout>これでナビゲーションやフッター、<head> タグなどを毎回書く必要がなくなりました。
#レイアウトのネスト
レイアウトを入れ子にすることもできます。例えば、ベースレイアウトの上にブログ専用のレイアウトを重ねるパターンです。
---import BaseLayout from './BaseLayout.astro';
interface Props { title: string; pubDate: string;}
const { title, pubDate } = Astro.props;---
<BaseLayout title={title}> <article> <h1>{title}</h1> <time datetime={pubDate}>{pubDate}</time> <hr /> <slot /> </article></BaseLayout>BlogPostLayout は BaseLayout をラップし、記事タイトルと日付を表示する構造を追加しています。
#Markdownレイアウト
Markdownファイルでは、frontmatterの layout プロパティでレイアウトを指定できます。
---title: はじめての記事pubDate: 2026-04-15layout: ../../layouts/BlogPostLayout.astro---
ここに記事の本文を書きます。Markdownの記法がそのまま使えます。layout に指定したレイアウトコンポーネントには、frontmatterの値が自動的にPropsとして渡されます。つまり BlogPostLayout 側で Astro.props.frontmatter.title のようにアクセスできます。
---// Markdownから使う場合、Propsの受け取り方が少し異なるconst { frontmatter } = Astro.props;const { title, pubDate } = frontmatter;---ただし、後の章で学ぶ Content Collections を使う場合は、この layout frontmatterではなく、[...slug].astro の動的ルートからレイアウトを直接指定する方法が推奨されます。
#コンポーネント分割の判断基準
「いつコンポーネントに切り出すか」は初心者がよく迷うポイントです。実践的な判断基準を提示します。
#コンポーネントに切り出すべきとき
- 同じHTMLの塊が2箇所以上で使われている — DRY原則の適用
- ページが長くなりすぎて読みづらい — 可読性の向上
- 独立して意味のある単位 — カード、ヘッダー、フッターなど
#コンポーネントに切り出さなくてよいとき
- 1箇所でしか使わない小さなHTML — 過度な分割は逆に読みづらい
- 将来使うかもしれないから — YAGNI原則(必要になったら切り出す)
- 行数を減らしたいだけ — 行数削減が目的なら、分割は適切でない場合がある
#推奨ディレクトリ構成
src/├── components/│ ├── common/ # サイト全体で使う共通コンポーネント│ │ ├── Header.astro│ │ ├── Footer.astro│ │ └── SEOHead.astro│ ├── blog/ # ブログ機能に関するコンポーネント│ │ ├── PostCard.astro│ │ └── TagList.astro│ └── ui/ # 汎用UIコンポーネント│ ├── Button.astro│ └── Card.astro├── layouts/│ ├── BaseLayout.astro # 全ページ共通の基盤レイアウト│ └── BlogPostLayout.astro└── pages/コンポーネントの分類に正解はありませんが、「用途別」に分けておくと見通しがよくなります。小規模なサイトでは components/ 直下にフラットに置くだけでも十分です。規模が大きくなってから整理しても遅くありません。
#まとめ
この章で学んだことを振り返ります。
- レイアウト —
<slot />を使ってページ共通の構造を共有する - レイアウトのネスト — レイアウトを入れ子にして構造を積み重ねられる
- Markdownレイアウト — frontmatterの
layoutプロパティでレイアウトを指定する - コンポーネント設計 — 切り出しの判断基準と推奨ディレクトリ構成
次の章では、スタイリングの方法を学びます。