Astroとは何か
高速なコンテンツサイトを作るためのフロントエンドフレームワーク
- Astroは、ブログ、ドキュメント、マーケティングサイト、ECの商品ページなど、コンテンツ中心のWebサイトに向いたJavaScriptフレームワークだ。
- 最大の特徴は、初期状態で不要なJavaScriptをブラウザへ送らず、必要な箇所だけをインタラクティブにする設計にある。
- React、Vue、Svelte、Preact、SolidなどのUIコンポーネントを組み合わせて使えるため、既存資産も活かしやすい。
- Markdown、MDX、CMS、APIなどのコンテンツを扱いやすく、型安全なContent Collectionsも備えている。
- SSR、API Routes、画像最適化、View Transitions、Server Islandsなども利用でき、静的サイトだけでなく動的な要件にも対応できる。
Astroの概要
Astroは「content-driven websites」、つまりコンテンツを中心にしたWebサイトのためのJavaScriptフレームワークだ。公式サイトでも、Astroは高速なマーケティングサイト、ブログ、ECサイトなどを作るためのフレームワークとして説明されている。Astro 6.1も公開済みで、現在も活発に開発されている。(Astro)
従来のReactやVueを中心にしたSPAでは、ページ全体をJavaScriptアプリケーションとして動かす構成になりやすい。一方、AstroはまずHTMLをサーバー側またはビルド時に生成し、ブラウザには必要最小限のJavaScriptだけを送る。この思想により、読み込み速度、Core Web Vitals、SEOに強い構成を作りやすい。
Astroが特に向いているのは、次のようなサイトだ。
- 技術ブログ
- 企業サイト
- LP
- ドキュメントサイト
- ポートフォリオ
- メディアサイト
- 商品紹介ページ
- CMS連携サイト
逆に、Figma、Notion、Slackのように画面全体が常に複雑に状態変化するWebアプリケーションでは、Next.js、Remix、Nuxtなどのアプリケーション寄りフレームワークの方が設計しやすい場合がある。
Astroの中心思想
Astroの中心にあるのは、HTMLを基本にし、JavaScriptを必要な場所にだけ足すという考え方だ。
公式サイトでは、Astroはサーバーでコンポーネントをレンダリングし、軽量なHTMLをブラウザへ送ることで、不要なJavaScriptのオーバーヘッドを避けると説明されている。また、Markdown、外部API、CMSなど、さまざまな場所にあるコンテンツを扱える設計になっている。(Astro)
この思想は、実装上は次のような形で表れる。
.astroファイルでHTMLに近いテンプレートを書く- ページの大半は静的HTMLとして出力する
- インタラクションが必要な部分だけReactやVueなどで実装する
client:load、client:idle、client:visibleなどで、いつJavaScriptを読み込むか制御する- 必要に応じてSSRやServer Islandsで動的部分を追加する
Islands Architectureとは
Astroを理解するうえで重要なのが、Islands Architectureだ。
Islands Architectureは、ページの大部分を静的HTMLとして描画し、カルーセル、検索フォーム、カートボタンなど、インタラクションが必要な小さな領域だけをJavaScriptで動かす設計である。公式ドキュメントでは、この方式により、現代的なフレームワークで問題になりがちな巨大なJavaScriptペイロードを避けられると説明されている。(Astro Docs)
たとえば、ブログ記事ページを考える。
ページ全体
├─ ヘッダー
├─ 記事本文
├─ 目次
├─ 関連記事
└─ コメント投稿フォーム
このうち、記事本文、ヘッダー、関連記事は静的HTMLで十分なことが多い。一方、コメント投稿フォームだけはブラウザ上で状態管理やAPI通信が必要になる。この場合、Astroではコメント投稿フォームだけをReactやVueのコンポーネントとして読み込ませられる。
---
import CommentForm from '../components/CommentForm.jsx';
---
<article>
<h1>Astroとは何か</h1>
<p>Astroはコンテンツ中心のWebサイトに向いたフレームワークだ。</p>
</article>
<CommentForm client:load />
client:loadを付けたコンポーネントだけがブラウザでハイドレーションされる。ハイドレーションとは、サーバーやビルド時に生成されたHTMLに対して、ブラウザ側でJavaScriptの動作を結びつける処理のことだ。
Zero JavaScript by default
Astroの特徴としてよく挙げられるのが、Zero JavaScript by defaultだ。これは「何もしなければ、ページに不要なJavaScriptを送らない」という意味である。
公式サイトでも、Astroは必要なJavaScriptだけを出荷し、残りを自動的に取り除くと説明されている。(Astro)
通常の.astroコンポーネントは、基本的にサーバー側またはビルド時にHTMLへ変換される。ブラウザ上で動くJavaScriptとしては送られない。
---
const title = 'Astro入門';
const description = 'Astroの基本を解説する記事';
---
<section>
<h1>{title}</h1>
<p>{description}</p>
</section>
このようなコンポーネントは、最終的には静的なHTMLに近い形で出力される。Reactコンポーネントのように、すべてがブラウザ上のJavaScriptアプリケーションとして動くわけではない。
React、Vue、Svelteなどを混在できる
Astroは特定のUIフレームワークにロックインされない。公式サイトでは、React、Vue、Preact、Svelte、Solidなどの主要UIフレームワークをサポートすると説明されている。(Astro)
Reactを使いたい場合は、次のように追加できる。
npx astro add react
Vueなら次のようになる。
npx astro add vue
Svelteなら次のようになる。
npx astro add svelte
Astroの面白い点は、プロジェクト内で複数のUIフレームワークを混在させられることだ。既存のReactコンポーネントを使いつつ、新しい一部のUIをSvelteで書く、といった構成も可能である。
ただし、混在できるからといって無闇に増やすべきではない。チーム開発では、基本は1つのUIフレームワークに寄せ、既存資産や外部ライブラリの都合がある場合だけ追加するのが扱いやすい。
ファイルベースルーティング
Astroはファイルベースルーティングを採用している。src/pages/配下のファイル構成が、そのままURL構造になる。公式ドキュメントでも、Astroはsrc/pages/ディレクトリのファイルレイアウトに基づいてビルドURLを生成すると説明されている。(Astro Docs)
例は次の通りだ。
src/pages/index.astro -> /
src/pages/about.astro -> /about
src/pages/blog/index.astro -> /blog
src/pages/blog/[slug].astro -> /blog/:slug
動的ルートも角括弧で表現できる。
src/pages/posts/[slug].astro
ブログ記事の詳細ページであれば、getStaticPaths()を使ってビルド時に生成するページ一覧を定義する。
---
export async function getStaticPaths() {
const posts = [
{ slug: 'hello-astro', title: 'Hello Astro' },
{ slug: 'astro-routing', title: 'Astroのルーティング' },
];
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
---
<h1>{post.title}</h1>
Content Collections
Astroでブログやドキュメントを作る場合、重要になるのがContent Collectionsだ。
Content Collectionsは、Markdown、MDX、JSON、YAML、外部CMSなどのコンテンツをコレクションとして扱う仕組みである。公式ドキュメントでは、コレクションはコンテンツとメタデータを取得し、型安全性、自動補完、バリデーションのためのスキーマを定義できると説明されている。(Astro Docs)
たとえば、ブログ記事のfrontmatterに型を付けたい場合は、次のように定義できる。
// src/content.config.ts
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const blog = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/blog' }),
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.coerce.date(),
tags: z.array(z.string()).default([]),
}),
});
export const collections = { blog };
記事側は次のように書く。
---
title: "Astro入門"
description: "Astroの基本を解説する"
pubDate: "2026-04-27"
tags: ["Astro", "Frontend"]
---
Astroはコンテンツ中心のWebサイトに向いたフレームワークだ。
これにより、frontmatterの不足や型の不一致を検出しやすくなる。ブログ、ニュース、ドキュメント、事例紹介など、同じ構造のコンテンツを大量に扱うサイトでは特に有効だ。
画像最適化
Astroには画像最適化の仕組みもある。公式ドキュメントでは、<Image />コンポーネントは画像を最適化し、処理可能な画像については元のアスペクト比からwidthとheightを推定してCLSを避けると説明されている。CLSはCore Web Vitalsの指標の1つで、ページ読み込み中のレイアウトずれを表す。(Astro Docs)
基本例は次の通りだ。
---
import { Image } from 'astro:assets';
import heroImage from '../assets/hero.png';
---
<Image src={heroImage} alt="サービス紹介のヒーロー画像" />
altは必須である。アクセシビリティの観点でも、画像の意味を説明するテキストを適切に設定する必要がある。
複数フォーマットを使いたい場合は<Picture />も利用できる。
---
import { Picture } from 'astro:assets';
import heroImage from '../assets/hero.png';
---
<Picture src={heroImage} alt="サービス紹介のヒーロー画像" formats={['avif', 'webp']} />
SSRとオンデマンドレンダリング
Astroは静的サイト生成だけでなく、SSRにも対応している。公式ドキュメントでは、Astroのページ、ルート、APIエンドポイントはデフォルトではビルド時に静的生成されるが、必要に応じてリクエスト時にサーバーでレンダリングできると説明されている。(Astro Docs)
SSRを使うには、デプロイ先に応じたアダプターを追加する。たとえばNode.jsなら次のようになる。
npx astro add node
Vercelなら次のようになる。
npx astro add vercel
Cloudflareなら次のようになる。
npx astro add cloudflare
個別ページだけSSRにしたい場合は、次のようにprerender = falseを指定する。
---
export const prerender = false;
const userAgent = Astro.request.headers.get('user-agent');
---
<h1>リクエストごとに生成されるページ</h1>
<p>{userAgent}</p>
サイト全体をSSR中心にする場合は、astro.config.mjsでoutput: 'server'を指定する。
// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({
mode: 'standalone',
}),
});
ただし、Astroの強みは静的HTMLを中心に高速化する点にある。すべてをSSRにする前に、本当にリクエスト時レンダリングが必要かを検討するべきだ。
API Routes
Astroでは、src/pages配下に.tsや.jsファイルを置くことでエンドポイントを作れる。公式ドキュメントでは、AstroのEndpointsは画像生成、RSS生成、API Routesなど、任意のデータを返すために使えると説明されている。(Astro Docs)
たとえば、JSONを返すAPIは次のように書ける。
// src/pages/api/status.json.ts
export function GET() {
return new Response(
JSON.stringify({
status: 'ok',
timestamp: new Date().toISOString(),
}),
{
headers: {
'Content-Type': 'application/json',
},
},
);
}
このファイルは/api/status.jsonとしてアクセスできる。
SSR環境では、POSTやPUTなどのHTTPメソッドを使ったAPIも実装できる。
// src/pages/api/contact.ts
export async function POST({ request }) {
const body = await request.json();
if (!body.email || !body.message) {
return new Response(
JSON.stringify({ error: 'email and message are required' }),
{ status: 400 },
);
}
return new Response(JSON.stringify({ ok: true }), {
headers: {
'Content-Type': 'application/json',
},
});
}
View Transitions
AstroはView Transitionsにも対応している。View Transitionsはページや状態の切り替え時にアニメーションを付け、視覚的な連続性を保つための機能だ。公式ドキュメントでは、AstroのView TransitionsはブラウザのView Transitions APIを利用し、fade、slide、noneなどの組み込みアニメーション、戻る・進む操作への対応、prefers-reduced-motionへの自動対応などを提供すると説明されている。(Astro Docs)
導入例は次の通りだ。
---
import { ClientRouter } from 'astro:transitions';
---
<html lang="ja">
<head>
<ClientRouter />
</head>
<body>
<slot />
</body>
</html>
画像や見出しなど、ページ間で連続して見せたい要素にはtransition:nameを付ける。
<img src="/hero.jpg" alt="ヒーロー画像" transition:name="hero" />
AstroのView TransitionsはSPA化そのものではない。基本はMPAのまま、必要なページ遷移体験だけを滑らかにできる点が特徴だ。
Server Islands
Server Islandsは、動的またはパーソナライズされた部分を、ページ全体のパフォーマンスを犠牲にせず個別にサーバーレンダリングする仕組みだ。公式ドキュメントでは、Server Islandsにより重要な部分を先に表示し、メインコンテンツをより積極的にキャッシュできると説明されている。(Astro Docs)
使い方は、対象コンポーネントにserver:deferを付ける。
---
import Avatar from '../components/Avatar.astro';
---
<Avatar server:defer />
フォールバック表示も指定できる。
---
import Avatar from '../components/Avatar.astro';
import GenericAvatar from '../components/GenericAvatar.astro';
---
<Avatar server:defer>
<GenericAvatar slot="fallback" />
</Avatar>
これにより、ページ本体は先に表示し、ユーザー固有のアバターや会員情報などは後から個別に取得して表示できる。静的サイトの速さと、動的コンテンツの柔軟性を両立しやすい。
Astroの始め方
Astroの新規プロジェクトは、公式ドキュメントで案内されているcreate astroコマンドで作成できる。現在の公式ドキュメントでは、前提条件としてNode.js v22.12.0以上が必要とされている。(Astro Docs)
npmなら次のコマンドを使う。
npm create astro@latest
pnpmなら次の通りだ。
pnpm create astro@latest
プロジェクト作成後は、一般的に次の流れで起動する。
cd my-astro-project
npm install
npm run dev
ビルドは次の通りだ。
npm run build
ローカルでビルド結果を確認する場合は次のコマンドを使う。
npm run preview
基本的なディレクトリ構成
Astroプロジェクトの基本構成は次のようになる。
my-astro-project/
├─ public/
├─ src/
│ ├─ assets/
│ ├─ components/
│ ├─ content/
│ ├─ layouts/
│ └─ pages/
├─ astro.config.mjs
├─ package.json
└─ tsconfig.json
主な役割は次の通りだ。
| ディレクトリ / ファイル | 役割 |
|---|---|
src/pages/ | ルーティング対象のページを置く |
src/components/ | 再利用するコンポーネントを置く |
src/layouts/ | ページ共通レイアウトを置く |
src/content/ | MarkdownやMDXなどのコンテンツを置く |
src/assets/ | Astroで処理する画像などを置く |
public/ | そのまま配信する静的ファイルを置く |
astro.config.mjs | Astroの設定を書く |
Astroコンポーネントの書き方
Astroコンポーネントは、フロントマターとテンプレート部分に分かれる。
---
const name = 'Astro';
const features = ['高速', '軽量', 'コンテンツ向き'];
---
<section>
<h1>{name}の特徴</h1>
<ul>
{features.map((feature) => (
<li>{feature}</li>
))}
</ul>
</section>
---で囲まれた部分はサーバー側で実行される。ここでデータ取得、変数定義、コンポーネントのimportなどを行う。
テンプレート部分では、HTMLに近い構文でマークアップを書く。JSXに似ているが、Astro独自の構文もある。
レイアウトの使い方
複数ページで共通のHTML構造を使いたい場合は、レイアウトコンポーネントを作る。
---
// src/layouts/BaseLayout.astro
const { title } = Astro.props;
---
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{title}</title>
</head>
<body>
<header>
<a href="/">My Site</a>
</header>
<main>
<slot />
</main>
<footer>
<small>© 2026 My Site</small>
</footer>
</body>
</html>
ページ側では次のように使う。
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout title="トップページ">
<h1>トップページ</h1>
<p>Astroで作ったサイトだ。</p>
</BaseLayout>
<slot />の部分にページ固有の内容が入る。
Astroのメリット
Astroの主なメリットは次の通りだ。
- 初期表示が速い
- 不要なJavaScriptを削減しやすい
- MarkdownやMDXとの相性がよい
- ReactやVueなどの既存コンポーネントを活かせる
- 静的サイト、SSR、API Routesを段階的に使い分けられる
- Content Collectionsでコンテンツを型安全に扱える
- 画像最適化やView Transitionsなど、サイト制作に必要な機能が揃っている
特に、記事やドキュメントのように「読むこと」が中心のサイトでは、Astroの設計がかなり合う。
Astroの注意点
Astroにも注意点はある。
まず、複雑なWebアプリケーションを作る場合、Astro単体では状態管理や画面遷移の設計が難しくなることがある。もちろんReactやVueを組み込めるが、アプリ全体が強いインタラクションを持つなら、最初からNext.jsやNuxtを選ぶ方が自然な場合もある。
次に、Islands Architectureの考え方に慣れる必要がある。ReactやVueの感覚で「全部クライアントで動く」と思って書くと、イベントハンドラが動かない、状態が保持されない、といった混乱が起きやすい。
たとえば、次のようなコードは.astroファイル上では期待通りにブラウザイベントとして動かない。
<button onClick={() => alert('clicked')}>Click</button>
ブラウザで動くインタラクションが必要な場合は、ReactやVueなどのコンポーネントに切り出し、client:*ディレクティブを付ける必要がある。
---
import Counter from '../components/Counter.jsx';
---
<Counter client:load />
Next.jsとの使い分け
AstroとNext.jsはどちらも優れたフレームワークだが、得意領域が異なる。
| 観点 | Astro | Next.js |
|---|---|---|
| 得意領域 | コンテンツサイト、ブログ、LP、ドキュメント | Webアプリ、ダッシュボード、SaaS |
| JavaScript | 必要な箇所だけ送る設計 | Reactアプリとして構成する |
| コンテンツ管理 | Markdown、MDX、Content Collectionsと相性がよい | CMS連携やApp Routerで柔軟に構成できる |
| インタラクション | Island単位で追加する | ページ・アプリ全体で扱いやすい |
| 学習の焦点 | Astro構文、Island、コンテンツ設計 | React、Server Components、App Router |
判断基準は単純だ。
コンテンツを読ませるサイトならAstroが向いている。ユーザーがログインして、画面上で多くの操作を行うアプリならNext.jsが向いている。
まとめ
Astroは、HTML、CSS、Markdownを中心にしながら、必要な部分にだけJavaScriptの力を足せるフレームワークだ。
特に優れているのは、次の点である。
- 静的HTML中心で高速に表示できる
- JavaScriptを必要最小限に抑えられる
- React、Vue、Svelteなどを部分的に使える
- MarkdownやCMSベースのコンテンツサイトを作りやすい
- SSR、API Routes、Server Islandsにより動的要件にも対応できる
ブログ、ドキュメント、企業サイト、LP、メディアサイトを作るなら、Astroはかなり有力な選択肢になる。Webサイトの本質が「アプリケーション」ではなく「コンテンツを届けること」にあるなら、まず検討する価値があるフレームワークだ。