シリーズ目次 / 前章: 02. Astroの環境構築とプロジェクト構成 / 次章: 04. Astroのレイアウトとスタイリング
Table of contents
Open Table of contents
この章のねらい
Astroでサイトを作るとき、いちばん多く書くのが .astro ファイルです。文法と、どこでいつ実行されるのかを押さえます。
.astro はHTMLの上位互換として作られています。正しいHTMLはそのまま .astro として通りますし、そこに機能がいくつか上乗せされているだけ、と考えると入りやすいはずです。
コンポーネントの二層構造
.astro ファイルは、大きく2つの部分に分かれます。
---
// ここがコンポーネントスクリプト(フロントマター)
const title = "はじめてのAstro";
const items = ["りんご", "みかん", "ぶどう"];
---
<!-- ここがコンポーネントテンプレート -->
<h1>{title}</h1>
<ul>
{items.map(item => <li>{item}</li>)}
</ul>
上の3本のハイフン(---)で囲まれた部分がコンポーネントスクリプト、その下がコンポーネントテンプレートです。この区切りは「コードフェンス」と呼ばれます。
2つの層は、実行される場所も届き方も違います。
コンポーネントスクリプト
コードフェンスの中には、通常のJavaScript(またはTypeScript)を書きます。ここでできることの例です。
- 他のコンポーネントやJSONデータのインポート
- APIやデータベースからのデータ取得
- 変数の定義や計算
このコードはサーバー側でしか実行されず、ブラウザには送信されません。ビルド時(静的生成の場合)かリクエスト時(オンデマンドレンダリングの場合)に実行され、その結果だけがHTMLとして届きます。
この性質のおかげで、APIキーを使った外部API呼び出しやデータベースアクセスをコンポーネント内に直接書いても、その内容が利用者のブラウザに漏れることはありません。
---
// この処理はサーバーでのみ実行される
const response = await fetch("https://api.example.com/posts");
const posts = await response.json();
---
<ul>
{posts.map(post => <li>{post.title}</li>)}
</ul>
コードフェンス内では await をそのまま使えます(トップレベルawait)。データ取得のために特別なフックや関数を覚える必要はありません。
コンポーネントテンプレート
テンプレートはHTMLですが、次の追加機能が使えます。
| 記法 | 意味 |
|---|---|
{式} | JavaScriptの式を評価して埋め込む |
{条件 && <p>表示</p>} | 条件つきで要素を出す |
{配列.map(...)} | 配列から要素を繰り返し生成する |
<Component /> | 他のコンポーネントを呼び出す |
class:list={...} | 条件に応じてクラス名を組み立てる |
見た目はJSXに似ていますが、.astro のテンプレートの土台はHTMLです。class を className に書き換える必要はありませんし、コメントも <!-- --> がそのまま通ります。
コンポーネントを組み合わせる
作ったコンポーネントは、インポートしてタグとして使います。
---
// src/pages/index.astro
import Card from "../components/Card.astro";
---
<main>
<Card title="お知らせ" />
<Card title="製品情報" />
</main>
インポートしたコンポーネント名は大文字で始めるのが慣例です(小文字だと通常のHTMLタグと区別がつかなくなるため)。
Props:外から値を受け取る
コンポーネントに値を渡すには、HTMLの属性と同じ書き方をします。受け取る側は Astro.props を使います。
---
// src/components/Card.astro
interface Props {
title: string;
description?: string;
}
const { title, description = "説明はありません" } = Astro.props;
---
<article class="card">
<h2>{title}</h2>
<p>{description}</p>
</article>
Props という名前でインターフェースを定義しておくと、Astroがそれを型として拾い、呼び出し側で補完とチェックが効きます。分割代入のデフォルト値で省略時の値を決められますし、? を付けた項目は任意、付けなければ必須になります。
文字列以外を渡すときは波かっこを使います。
<Card title="製品情報" tags={["新着", "特集"]} count={3} />
slot:中身を差し込む
Propsは「値」を渡す仕組みですが、「HTMLのかたまり」を渡したいこともあります。そのための仕組みが <slot /> です。
---
// src/components/Panel.astro
---
<section class="panel">
<slot />
</section>
呼び出し側でタグの中に書いた内容が、<slot /> の位置に入ります。
<Panel>
<h2>タイトル</h2>
<p>本文です。</p>
</Panel>
名前付きスロット
差し込み口が複数必要なときは、name 属性で区別します。
---
// src/components/Layout.astro
---
<div class="wrapper">
<header>
<slot name="header" />
</header>
<main>
<slot />
</main>
<footer>
<slot name="footer" />
</footer>
</div>
呼び出し側は slot="名前" 属性で対応づけます。
<Layout>
<h1 slot="header">サイト名</h1>
<p>本文はここに入ります。</p>
<small slot="footer">© 2026</small>
</Layout>
name を持たない <slot /> は「その他すべて」の受け皿になります。
呼び出し側とコンポーネント側の対応は次のとおりです。
フォールバックコンテンツ
スロットに何も渡されなかったときの既定値を、<slot> の中に書いておけます。
<slot name="header">
<h1>既定のタイトル</h1>
</slot>
コンテンツが渡されればそちらが優先され、渡されなければ既定値が表示されます。
クライアント側で動くスクリプト
コンポーネントスクリプトはサーバーでしか動かないため、ボタンのクリックに反応するようなコードは <script> タグに書きます。
<button id="toggle">切り替え</button>
<script>
document.getElementById("toggle")?.addEventListener("click", () => {
document.body.classList.toggle("dark");
});
</script>
テンプレート内の <script> は、既定でAstroによってバンドル・最適化されます。処理させたくない場合は is:inline ディレクティブを付けると、書いたままの形でHTMLに出力されます。
なお、<script> の中からコンポーネントスクリプトの変数を直接参照することはできません。両者は実行される場所も時点も違うためです。値を渡したいときは、data-* 属性を経由するのが定石です。
---
const message = "こんにちは";
---
<button id="greet" data-message={message}>あいさつ</button>
<script>
const button = document.getElementById("greet");
button?.addEventListener("click", () => {
alert(button.dataset.message);
});
</script>
より本格的な対話機能が必要な場合は、ReactやSvelteのコンポーネントをアイランドとして持ち込む方法があります。これは08. AstroのアイランドアーキテクチャとUIフレームワークで扱います。
HTMLの厳密さに注意(Astro 7)
Astro 7では .astro のコンパイラがRustで書き直され、不正なHTML構文に対して以前より厳しくなりました。具体的には、次のようなコードがエラーになります。
- タグの閉じ忘れ(
<div>に対応する</div>がない) - 属性の書きかけ(引用符の閉じ忘れなど)
一方、<p> の中に <div> を置くような、構文上は閉じていても意味的に不正なネストはコンパイルエラーになりません。以前のコンパイラはこの手のHTMLを黙って直していましたが、Astro 7はそのまま出力してブラウザのHTMLパーサーに投げます。レイアウトが意図せず崩れるので、エディタのフォーマッタと astro check を通したうえで、生成結果も自分の目で見てください。
要点
.astroはコードフェンス(---)で区切られたスクリプト部とテンプレート部からなる。- コンポーネントスクリプトはサーバーでのみ実行され、ブラウザには送信されない。トップレベル
awaitも使える。 Propsインターフェースを定義すると、呼び出し側で型チェックと補完が効く。<slot />でHTMLのかたまりを差し込める。名前付きスロットとフォールバックも使える。- ブラウザで動かす処理は
<script>タグに書き、値の受け渡しはdata-*属性を経由する。
参考資料
- Astro Components — Astro Docs
- Template Directives Reference — Astro Docs
- Upgrade to Astro v7 — Astro Docs
シリーズ目次 / 前章: 02. Astroの環境構築とプロジェクト構成 / 次章: 04. Astroのレイアウトとスタイリング