- 技術 💻
Astroとは・使い方入門|JSゼロのブログをNext.jsと実測比較
結論
Astro(アストロ)は、ページをビルド時に HTML として書き出し、動きが要る部品(アイランド)にだけ JavaScript を送る Web フレームワークです。ブログ・ドキュメント・企業サイトのように「読ませる」サイトに向いています。
この記事でわかること
- Astro 7.4 でブログを作る手順と、各コマンドの実際の出力
- client:load などで送られる JS の量(Next.js・素の HTML と実測比較)
- Content Collections・Markdown・SSR とよくあるエラーの原文
Astro の考え方は「まず HTML を作り、JavaScript は必要な所にだけ足す」です。何も指定しなければ、ページは JavaScript なしの HTML になります。
flowchart TD
S[.astro・.md のソース] --> B[astro build]
B --> H[HTML<br>JSは0バイト]
B --> J[島のJS<br>client:* を付けた部品だけ]
H --> V[ブラウザ]
J -->|load・idle・visible・media| V
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| Astroとは | コンテンツ中心のサイト向けの Web フレームワーク。既定で JS を送らない | Astroとは |
| Astroの使い方(始め方) | npm create astro@latest か、npm install astro で手動作成 |
インストールとプロジェクト作成 |
| Astroは何の言語で書くか | HTML に近い .astro ファイル+JavaScript/TypeScript。Markdown も使える | .astroファイルの書き方 |
| アイランドとは | ページの中で JS を持つ部品だけを「島」として動かす仕組み | Astroのアイランド |
| JSはどれだけ減るか | 記事一覧は Astro 0バイト・Next.js 約115KB(brotli)だった | JavaScriptの量を実測 |
| React は使えるか | 使える。npx astro add react で追加し、部品に client:* を付ける |
Astroのアイランド |
| Next.jsとの違い | Astro は読ませるサイト、Next.js はログイン後の画面が多いアプリ向き | AstroとNext.jsの違い |
| SSR(サーバー描画)はできるか | できる。アダプターを入れ、ページ単位で prerender = false |
オンデマンド描画 |
確認環境:Ubuntu 24.04.5 LTS(Intel Xeon 2.10GHz・2コア)の上で、Node.js 22.23.4・npm 10.9.9 を使いました。最初の実行より前に ASTRO_TELEMETRY_DISABLED=1 と NEXT_TELEMETRY_DISABLED=1 を設定し、npm のキャッシュとプロジェクトはすべて作業用のフォルダーに置いています。Astro 7.4.4(Vite 8.3.5)を公式の「手動インストール」の手順で入れ、ブログ(Markdown 3本・Content Collections)を作り、@astrojs/react 7.1.2(React 19.3.1)、@astrojs/preact 6.1.1(Preact 11.1.0)、@astrojs/node 11.1.9、@astrojs/check 0.9.12(TypeScript 6.0.3)を追加しました。比較用に Next.js 16.4.3(Turbopack)で同じ画面を作り、素の HTML も用意しています。サーバーはすべて 127.0.0.1 の自分のポートで起動し、読み込まれた JavaScript の量と動きは Chromium 153.0.8010.12(playwright-core 1.63.0)で測りました。create astro のテンプレートは、この環境では GitHub から取得できなかったため、テンプレートの中身と Node.js の要件、Astro 7 の変更点、デプロイ先、Cloudflare との関係は Astro の公式ドキュメントと公式ブログで確かめています。図は mermaid 11.16.0 で描画を確かめました(確認日 2026年10月29日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Astroとは・使い方入門|JSゼロのブログをNext.jsと実測比較」
Astroとは(Webフレームワークの特徴)
この節では、Astro がどんなフレームワークで、何が得意なのかが分かります。
Astro は、ブログ・ドキュメント・マーケティングサイト・EC のような「コンテンツを見せるサイト」を速く作るための Web フレームワークです。 公式ドキュメントは、Astro の設計の柱として次の5つを挙げています。
コンテンツ駆動
アプリよりも、記事や商品情報を見せることを優先して設計されている。
ブログ・ドキュメント向き
サーバーファースト
HTML をサーバー(またはビルド時)で作り、閲覧する端末の処理を減らす。
ブラウザでの描画は必要な所だけ
既定で速い
何も指定しなければ JavaScript を送らない。手元のブログも JS は0バイトだった。
ゼロ JS が初期値
簡単に使える
.astro は HTML に近い書き方。複雑な機能は必要になったら足す(オプトイン)。
HTML が書ければ始められる
5つ目は「開発者を重視」で、CLI・VS Code の拡張機能・TypeScript への対応・日本語を含む多言語のドキュメントがそろっています。React・Preact・Svelte・Vue・Solid の部品をそのまま混ぜて使えるのも特徴です。
Astroの版と運営(2026年10月29日時点)
- Astro を開発する The Astro Technology Company は、2026年1月16日に Cloudflare に加わりました。公式ブログは「Astro stays open-source and MIT-licensed」と書き、Cloudflare 以外の多くのデプロイ先への対応も続けるとしています。
- Astro 7.0 では、開発サーバーと本番のバンドラーが Vite 8 になり、コンパイラーが Go 製から Rust 製に替わり、Markdown の処理が Sätteri(サッテリ)という新しい仕組みに変わりました(公式の移行ガイド)。手元の 7.4.4 でも、設定の中の Markdown の処理系は
satteriになっていました。
Astroの使い方:インストールとプロジェクト作成(create astro)
この節では、Astro のプロジェクトを作る2つの方法と、テレメトリー(利用状況の送信)を止める方法が分かります。
ふつうは npm create astro@latest の対話形式で作ります。 テンプレートを選ぶと、--template で公式の例(blog・minimal など)から始められます。
# テレメトリーを送らない(最初の実行より前に設定する)
export ASTRO_TELEMETRY_DISABLED=1
# 対話形式で作る
npm create astro@latest
# ブログのテンプレートから作る
npm create astro@latest my-blog -- --template blog
テレメトリーは、npx astro telemetry disable でも止められます。公式の CLI リファレンスは、CI では astro telemetry disable を実行するか ASTRO_TELEMETRY_DISABLED を設定する、と書いています。
テンプレートが取れないときは手動で作る
手元の環境では、GitHub への接続が止められているため、テンプレートの取得で止まりました。社内のプロキシなどで GitHub に出られないときも、同じ表示になります。
$ npm create astro@latest blog -- --template blog --install --no-git --yes
astro Launch sequence aborted.
▲ error Template blog could not be found!
◼ check https://astro.build/examples
npm error code 1
テンプレートは npm ではなく GitHub から取得されるため、npm のパッケージは入れられても、テンプレートだけ取れないことがあります。 そのときは、公式ドキュメントの「手動インストール」の手順で作れます。npm のレジストリーに届けば作れることを、手元で確かめました。
フォルダーを作り、npm init する
mkdir blog && cd blog && npm init --yes。package.json に "type": "module" を足す。
Astro をローカルに入れる
npm install astro。公式はグローバルではなくプロジェクトの中に入れるよう書いている。手元では 192 個のパッケージが24秒で入り、node_modules は 154MB だった。
scripts を書く
"dev": "astro dev"、"build": "astro build"、"preview": "astro preview" の3つ。
最初のページを置く
src/pages/index.astro を作る。public/ のファイル(robots.txt など)はそのまま出力に入る。
設定ファイルと tsconfig.json を置く
astro.config.mjs(無くても動く)と、astro/tsconfigs/strict などを継承した tsconfig.json。
{
"type": "module",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
}
}
Node.js は 22.23.4 以上が要ります。 公式ドキュメントは v23 のような奇数の版は対象外としています。npm の astro 7.4.4 の engines にも node: '>=22.23.4' と書かれていました。Node.js 自体は、公式サイトから LTS の版を入れるのが確実です。
ディレクトリ構成と.astroファイルの書き方
この節では、Astro のフォルダーの役割と、.astro ファイルの書き方が分かります。
手元で作ったブログの構成です。
blog/
├─ astro.config.mjs 設定(インテグレーション・アダプター)
├─ tsconfig.json
├─ public/robots.txt そのまま出力にコピーされる
└─ src/
├─ content.config.ts Content Collections の定義
├─ content/blog/*.md 記事(Markdown)
├─ layouts/Base.astro 共通のレイアウト
├─ components/ 部品(.astro・React・Preact)
└─ pages/ ここに置いたファイルが URL になる
├─ index.astro → /
├─ about.astro → /about/
└─ blog/[id].astro → /blog/記事のID/
.astro ファイルは、上の --- で囲んだ部分(コンポーネントスクリプト)と、下の HTML の部分(テンプレート)でできています。 上の部分はビルド時(またはサーバー)でだけ実行され、ブラウザには送られません。
---
// ここはビルド時に実行される(ブラウザには送られない)
interface Props { title: string; description?: string }
const { title, description = 'Astroで作ったブログ' } = Astro.props;
---
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>{title}</title>
<meta name="description" content={description} />
</head>
<body>
<main><slot /></main> <!-- 呼び出し側の中身がここに入る -->
</body>
</html>
<style>
main { max-width: 40rem; margin: 0 auto; } /* このファイルだけに効く */
</style>
| 書き方 | 意味 | 手元の出力で見えたこと |
|---|---|---|
{title} |
値を埋め込む(エスケープされる) | HTML の中に文字として入った |
{posts.map(...)} |
配列から要素を並べる(JSX に近い) | li がビルド時に展開された |
<slot /> |
レイアウトに中身を差し込む | 各ページの main に入った |
<style> |
そのファイルだけに効く CSS | data-astro-cid-… 属性が付いて範囲が限られた |
<script> |
ブラウザで動く JS(TypeScript も可) | 小さいので HTML に埋め込まれ、圧縮された |
React と違い、className ではなく class、onClick={関数} ではなく <script> でイベントを付けます。.astro の中で onclick={hello} と書くと、関数が文字列のまま属性に入りました(つまずきの節で原文を載せています)。
ルーティングとページの作り方(src/pages・動的ルート)
この節では、URL とファイルの対応と、記事ごとのページを作る getStaticPaths() が分かります。
Astro は src/pages/ の中のファイルの場所が、そのまま URL になります(ファイルベースのルーティング)。 [id].astro のように角かっこを使うと、1つのファイルから複数のページを作れます。
---
// src/pages/blog/[id].astro
import { getCollection, render } from 'astro:content';
import Base from '../../layouts/Base.astro';
export async function getStaticPaths() {
const posts = await getCollection('blog', ({ data }) => !data.draft);
return posts.map((post) => ({ params: { id: post.id }, props: { post } }));
}
const { post } = Astro.props;
const { Content, headings } = await render(post);
---
<Base title={post.data.title} description={post.data.description}>
<article>
<h1>{post.data.title}</h1>
<p>タグ:{post.data.tags.join('・')}/見出し {headings.length} 個</p>
<Content />
</article>
</Base>
- 静的に書き出すとき(既定)は、動的ルートに
getStaticPaths()が必須です。 消すと、ビルドがGetStaticPathsRequiredで止まりました。 - はじめは
getCollection('blog')と全件を渡していたため、draft: trueの下書きも/blog/draft/index.htmlとして出力されました。一覧で下書きを除いても、個別のページは別に作られます。上のようにgetStaticPaths()の中でも絞ると、出力は2ページに減りました。 - ID に「/」を含むとき(フォルダー分けした記事など)は、
[...id].astroの形にします(公式)。
MarkdownとContent Collectionsでブログを作る
この節では、Markdown の記事を型付きで扱う Content Collections の書き方と、ビルドで分かる誤りが分かります。
Content Collections は、Markdown などの記事を「コレクション」として登録し、フロントマター(記事の先頭の情報)をスキーマで検査する仕組みです。 定義は src/content.config.ts に書きます。
// src/content.config.ts
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const blog = defineCollection({
loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.coerce.date(), // '2026-10-01' も Date になる
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = { blog };
記事は、フロントマターと本文を Markdown で書きます。
---
title: 'はじめての投稿'
description: 'Astroで最初に書いた記事です'
pubDate: '2026-10-01'
tags: ['astro', 'はじめに']
---
## Markdownで書ける
**太字**や[リンク](https://docs.astro.build/)、表も書けます。
ビルドすると、見出しに id が付き、コードブロックはビルド時に色付けされた HTML(Shiki の github-dark)になりました。ブラウザでの色付け用の JS は送られていません。
<h2 id="markdownで書ける">Markdownで書ける</h2>
<p><strong>太字</strong>や<a href="https://docs.astro.build/">リンク</a>、表も書けます。</p>
<pre class="astro-code github-dark" ... data-language="js"><code><span class="line">...
スキーマに合わない記事はビルドで止まる
description を書き忘れ、pubDate に「あした」と書いた記事を置くと、次の原文でビルドが止まりました。
[InvalidContentEntryDataError] blog → broken data does not match collection schema.
description**: **description: Required
pubDate**: **pubDate: Expected type `"date"`, received `"object"`
Hint:
See https://docs.astro.build/en/guides/content-collections/ for more information on content schemas.
Location:
/dev/shm/t42/blog/src/content/blog/broken.md:0:0
記事が増えても、日付の書き間違いや項目の抜けを公開前に見つけられるのが Content Collections の利点です。 フロントマターの型はエディターの補完にも使われます。
1getCollection の順番は決まっていない
公式は順番を保証していない。新しい順に並べるなら sort() を自分で書く。
21件だけなら getEntry
getEntry('blog', 'first-post') で ID を指定して取り出す。
3本文は render で描く
render(post) が返す Content を置く。headings で目次も作れる。
Markdown の記法そのものは、関連記事「Markdownの書き方一覧|記法早見表と環境別の対応・変換結果つき」で扱っています。
Astroのアイランド(client:load・client:visible など)
この節では、アイランドの意味と、client:* の種類ごとに JS がいつ読み込まれるかが、Chromium で測った結果で分かります。
アイランド(島)は、静的な HTML の海の中に、JavaScript で動く部品だけを島のように置く考え方です。 Astro では、React などの部品に client:* を付けたときだけ、その部品の JS がブラウザに送られます。付けなければ、部品は HTML として描かれるだけで動きません。
React を足すと、npx astro add react が astro.config.mjs と tsconfig.json を書き換えました(9.3秒)。
$ npx astro add react --yes
Astro will make the following changes to your config file:
import react from '@astrojs/react';
export default defineConfig({
site: 'https://example.com',
integrations: [react()],
});
success Added the following integration to your project:
- @astrojs/react
success Successfully updated tsconfig
押すと数が増えるだけの React の部品を、ディレクティブを変えて置きました。
---
import Counter from '../../components/react/Counter.jsx';
---
<Counter /> <!-- JS を送らない -->
<Counter client:load /> <!-- すぐ読み込む -->
<Counter client:idle /> <!-- ブラウザが空いたら -->
<Counter client:visible /> <!-- 画面に入ったら -->
<Counter client:media="(max-width: 600px)" /> <!-- 条件に合ったら -->
<Counter client:only="react" /> <!-- サーバーで描かない -->
| ディレクティブ | JS を読み込む時 | 手元の結果(Chromium) |
|---|---|---|
| なし | 読み込まない | JS 0個。ボタンは出るが押しても「いいね 0」のまま |
client:load |
ページを開いてすぐ | JS 3個。押すと「いいね 1」 |
client:idle |
読み込みが終わり、ブラウザが空いた時 | JS 3個。押すと「いいね 1」 |
client:visible |
部品が画面に入った時 | スクロール前は0個、3000px 下までスクロールして3個 |
client:media |
メディアクエリに合った時 | 幅1280px では0個で動かず、幅400px では3個で動いた |
client:only |
すぐ(サーバーでは描かない) | JS 3個。JS を切るとボタン自体が無い |
client:idle には待つ上限({{timeout: 500}})、client:visible には手前で読み込む余白({{rootMargin: "200px"}})を付けられます(公式)。client:only は、どのフレームワークかを値で伝える決まりです。
出力された HTML では、島は <astro-island> という要素で包まれ、読み込む JS の場所と条件が属性に入っていました。サーバーで描いたボタンが先に入っているため、JS が届く前から表示されます。
<astro-island uid="Z1LWRyz" prefix="r1" component-url="/_astro/Counter.D-hcgzNV.js"
component-export="default" renderer-url="/_astro/client.Cd-EeyjT.js" props="{}"
ssr client="load" ...><button type="button">いいね 0</button></astro-island>
client:* を付けない部品
サーバーで HTML にするだけ
JS は送られない(0バイト)
見出し・カード・記事の本文に向く
client:* を付けた部品(島)
ブラウザで動く(ハイドレーション)
部品と UI ライブラリの JS が届く
検索窓・いいね・カルーセルに向く
送られるJavaScriptの量を実測(Astro・Next.js・素のHTML)
この節では、同じ画面を Astro・Next.js・素の HTML で作ったとき、ブラウザが読み込む JavaScript の量の違いが分かります。
記事一覧のページは、Astro では JS が0バイト、Next.js 16 では5ファイル・約115KB(brotli 圧縮後)でした。 ボタン1つの画面では、Astro の React の島が約59KB、Preact の島なら約7KB でした。各ページを Chromium で開き、読み込まれた script を全部数えています(圧縮後の大きさは、受け取った中身を gzip -9・brotli で圧縮し直した値です)。
| 作り方 | HTML | JS の数 | JS(圧縮なし) | JS(brotli) |
|---|---|---|---|---|
| 素の HTML(script をじかに書く) | 363B | 0 | 0B | 0B |
| Astro・記事一覧 | 839B | 0 | 0B | 0B |
| Astro・<script> でボタン | 758B | 0(HTML に埋め込み) | 0B | 0B |
| Astro・Preact の島1つ | 6,054B | 4 | 16,899B | 6,950B |
| Astro・React の島1つ | 6,052B | 3 | 221,279B | 59,791B |
| Astro・React の島3つ | 6,843B | 3 | 221,279B | 59,791B |
| Next.js 16・記事一覧 | 5,121B | 5 | 455,990B | 115,166B |
| Next.js 16・ボタン1つ | 5,492B | 6 | 456,318B | 115,387B |
- Astro の React の島の JS の大半は React 本体です。 3ファイルのうち、
client.*.js(React DOM を含む)が 212,836B、部品自体のCounter.*.jsは 534B でした。島を3つにしても、共通の部分は1回しか読み込まれず、量は変わりませんでした。 - Preact に替えると、同じ部品で JS は約8分の1(brotli で 59,791B→6,950B)になりました。
- Next.js は、ページにクライアントの部品が無くても、ルーターと React の実行に使う JS を読み込みます。ボタンを足したときの増加は、部品の 328B の1ファイルだけでした。
- 島を置くと、Astro の HTML は約5.4KB 増えました(島なしのボタンのページ 616B → client:load のページ 6,052B)。
<astro-island>を動かす小さなスクリプトが HTML に埋め込まれるためです。
この数値は「どちらが良いか」ではなく、得意な範囲の違いを示しています。 Next.js の JS には、ページ移動を速くするクライアント側のルーターなどが入っており、ログイン後の画面が多いアプリではそれが役立ちます。Next.js の入門は、関連記事「Next.js App Router 入門|v16対応・実際のビルド結果つき」で扱っています。
ビルドと出力(astro build・astro preview)
この節では、astro build で何が作られるか、ビルドの時間、確かめ方が分かります。
astro build は、既定では全ページを HTML として dist/ に書き出します(静的サイト生成)。 最初のブログ(Markdown 3本・ページ3種類)のビルドの出力です。
$ npx astro build
21:48:48 [content] Syncing content
21:48:49 [content] Synced content
21:48:49 [build] output: "static"
21:48:49 [build] mode: "static"
21:48:49 [build] directory: /dev/shm/t42/blog/dist/
21:48:49 [build] Building static entrypoints...
21:48:49 [vite] ✓ built in 642ms
generating static routes
21:48:49 ├─ /about/index.html (+30ms)
21:48:49 ├─ /blog/draft/index.html (+5ms)
21:48:49 ├─ /blog/first-post/index.html (+3ms)
21:48:49 ├─ /blog/islands/index.html (+5ms)
21:48:49 ├─ /index.html (+38ms)
21:48:49 [build] 5 page(s) built in 3.66s
21:48:50 [build] Complete!
出力は HTML 5つと robots.txt だけで、_astro/ のフォルダー(JS の置き場)はできませんでした。トップの HTML は 839B で、<script> は1つもありません。
| 試したこと | ページ数 | かかった時間 | dist の大きさ |
|---|---|---|---|
| 記事3本(島のページ込み) | 14 | 3.1秒 | 約0.9MB |
| 記事を503本に増やした1回目 | 514 | 6.2秒 | 2.9MB |
| 同じ内容の2回目 | 514 | 5.4秒 | 2.9MB |
どれも Node.js のアダプターを入れた状態で、時間はコマンドを打ってから終わるまで(2コアの環境)です。記事が500本増えても、ビルドは約3秒延びただけでした。
astro preview で出力を確かめる
astro preview は dist/ を手元で配信して、本番に近い形で確かめるコマンドです。手元では、次のように表示して裏で動き続けました。
$ npx astro preview --host 127.0.0.1 --port 45421
{"message":"Preview server running at http://127.0.0.1:45421 (pid 3832)\n Stop: astro preview stop\n Status: astro preview status\n Logs: astro preview logs", ...}
これは Astro 7 の --background の動きです。 公式の CLI リファレンスは、AI エージェントが検出されると macOS と Linux では --background が自動で付き、JSON のログになる、と書いています(Windows では自動にならない)。手元ではエージェントから実行したため、裏で動きました。ふつうにターミナルで打てば前面で動き、Ctrl+C で止まります。裏で動いているときは astro preview stop・status・logs で操作できます。
開発サーバー(astro dev)と型チェック(astro check)
この節では、開発中の画面の確かめ方と、ビルドでは見つからない誤りを見つける方法が分かります。
npm run dev(astro dev)で開発サーバーが起動し、既定では http://localhost:4321/ で開けます。手元のログには次の行が出ました。
astro v7.4.4 ready in 1795 ms
┃ Local http://127.0.0.1:45424/
watching for file changes...
[200] /blog/first-post/ 154ms
- Chromium で記事を開いたまま、Markdown のタイトルを書き換えると、822ミリ秒後に画面のタイトルが新しくなりました。 ログには
Reloaded data from first-post.mdと出ました。 - 開発中のページの下には、Astro の開発ツールバーが表示されました。開発時だけ
/@vite/clientなどのスクリプトが入り、本番の出力には入りません。 - 同じプロジェクトで2つ目の
astro devを打つと、Dev server already running at http://127.0.0.1:45424 (pid 9037)と出て、新しく起動しませんでした(.astro/dev.jsonのロックファイル)。
astro check:ビルドが通っても型の誤りを見つける
記事一覧で post.data.title を post.data.titel と書き間違えても、astro build は成功し、リンクの文字が空の HTML ができました。 astro check(@astrojs/check と typescript を入れる)を使うと、次のように見つかり、終了コードは 1 でした。
$ npx astro check
src/pages/index.astro:13:50 - error ts(2551): Property 'titel' does not exist on type '{ title: string; description: string; pubDate: Date; tags: string[]; draft: boolean; }'. Did you mean 'title'?
13 <a href={`/blog/${post.id}/`}>{post.data.titel}</a>
~~~~~
Result (21 files):
- 1 error
- 0 warnings
- 8 hints
型は Content Collections のスキーマから作られています。CI では、astro check && astro build の順に動かすと、型の誤りで止められます。
オンデマンド描画とサーバーアイランド(SSR・アダプター)
この節では、リクエストのたびに HTML を作るページと、ページの一部だけを後から描く server:defer の動きが分かります。
Astro は既定では全ページを静的に書き出しますが、アダプターを入れると、選んだページだけをリクエストのたびに描けます。 公式のアダプターは Node.js・Netlify・Vercel・Cloudflare の4つです。npx astro add node で Node.js のアダプターを足しました。
---
// src/pages/now.astro
export const prerender = false; // このページだけリクエストのたびに描画する
const now = new Date().toISOString();
const ua = Astro.request.headers.get('user-agent');
---
<p id="now">{now}</p>
<p>User-Agent:{ua}</p>
ビルドの表示は mode: "server"・adapter: @astrojs/node になり、出力は dist/client/(静的なファイル)と dist/server/entry.mjs(サーバー)に分かれました。HOST=127.0.0.1 PORT=45425 node dist/server/entry.mjs で起動して、2回続けて開いた結果です。
[@astrojs/node] Server listening on http://127.0.0.1:45425
$ curl -A curl-test/1 http://127.0.0.1:45425/now
<p id="now">2026-10-29T12:54:53.365Z</p>
<p>User-Agent:curl-test/1</p>
$ curl -A curl-test/2 http://127.0.0.1:45425/now
<p id="now">2026-10-29T12:54:53.379Z</p>
<p>User-Agent:curl-test/2</p>
時刻と User-Agent がリクエストごとに変わりました。ほかのページは静的な HTML のまま配信され、Cache-Control: public, max-age=0 と ETag が付いていました。
server:defer(サーバーアイランド)
ページの大半は静的にして、在庫やログイン中の名前のような「人や時刻で変わる部分」だけを後から描くのがサーバーアイランドです。1秒かかる在庫の部品に server:defer を付けました。
<Stock server:defer>
<p slot="fallback">在庫を読み込み中…</p>
</Stock>
req 274 ms GET /_server-islands/Stock?e=...
DOMContentLoaded 275 ms: 商品ページ(ビルド時に作った静的HTML)… 在庫を読み込み中…
island 1702 ms: 在庫:8個(2026-10-29T12:55:07.003Z)
reload: 在庫:5個(2026-10-29T12:55:08.494Z)
ページ本体は275ミリ秒で表示され、遅い部品だけが約1.4秒後に差し込まれました。 読み込み直すと在庫の数と時刻が変わり、その部分だけが毎回サーバーで描かれていることが分かります。公式ドキュメントは、server:defer にはアダプターが要るとしています。
AstroとNext.jsの違い(判断表)
この節では、Astro と Next.js のどちらを選ぶかを、作るものから決める方法が分かります。
「読ませるページが中心なら Astro、ログイン後に操作する画面が中心なら Next.js」が基本の線引きです。 手元の比較と公式ドキュメントの記述をもとにまとめました。
| 比べる点 | Astro 7 | Next.js 16 |
|---|---|---|
| 得意なもの | ブログ・ドキュメント・企業サイト・LP | 管理画面・SaaS・会員サイトなどのアプリ |
| 既定の JS | 0バイト(島を置いた分だけ増える) | 静的なページでも React とルーターの JS が届く |
| UI の書き方 | .astro(HTML に近い)。React・Vue・Svelte なども混ぜられる | React(Server Components と Client Components) |
| ページ移動 | ふつうのページ移動(MPA) | クライアント側のルーターで部分的に入れ替える |
| Markdown の記事 | 標準で扱える。Content Collections で型付き | MDX などを追加して組む |
| サーバー処理 | アダプターを入れてページ単位で SSR・Actions | Route Handlers・Server Actions を標準で使う |
| 手元のビルド | 14ページ 3.1秒 | 3ルート 7.0秒(Turbopack) |
- 1ページの大半が記事・説明・商品の紹介 → Astro動く部分は島にする。検索窓・フォームも島で足せる
- 2ログイン後の画面が中心で、画面の状態をページ間で持ち回る → Next.js島どうしでは React の Context が使えず、公式は Nano Stores をすすめている
- 3サイトとアプリが両方ある → 分けて作る公開サイトは Astro、/app 以下は Next.js などに分ける
- 4チームが React しか書けない → どちらでもよいAstro でも React の部品をそのまま島として使える
選び方の誤り
見分ける問い:「この部品は、押したり入力したりするか」
Astroのよくあるエラーとつまずき(原文つき)
この節では、Astro で出やすいエラーの原文と、原因・直し方が分かります。すべて手元で出したものです。
| 表示(原文) | 原因 | 直し方 |
|---|---|---|
error Template blog could not be found! |
テンプレートを GitHub から取れない(プロキシ・社内の制限) | GitHub へ出られる回線で作るか、手動インストール |
[InvalidContentEntryDataError] ... does not match collection schema. |
フロントマターがスキーマに合わない | 表示された項目(Required・Expected type)を直す |
[GetStaticPathsRequired] `getStaticPaths()` function is required for dynamic routes. |
静的出力の [id].astro に getStaticPaths が無い |
getStaticPaths を export する。SSR にするなら prerender = false |
Error: Unable to render Width! |
部品がサーバーでの描画中に window を使った |
client:only="react" にするか、useEffect の中で使う |
NoClientOnlyHint: Unable to render `Width`. |
client:only に値が無い |
client:only="react" のようにフレームワーク名を書く |
NoMatchingRenderer: Unable to render `Counter`. |
.jsx を描くインテグレーションが入っていない | npx astro add react など |
[WARN] [glob-loader] The base directory ... does not exist. |
glob の base のフォルダー名の誤り |
パスを直す(ビルドは通り、一覧が0件になった) |
error ts(2551): Property 'titel' does not exist |
フロントマターの項目名の書き間違い | astro check で見つけて直す(build は通る) |
window を使う部品の原文
window.innerWidth を表示するだけの React の部品に client:load を付けると、ビルドが止まりました。client:load でも、最初の HTML はサーバーで描かれるためです。
[ERROR] Error: Unable to render Width!
This component likely uses @astrojs/react, @astrojs/preact, @astrojs/solid-js or @astrojs/vue (jsx),
but Astro encountered an error during server-side rendering.
Please ensure that Width:
1. Does not unconditionally access browser-specific globals like `window` or `document`.
If this is unavoidable, use the `client:only` hydration directive.
2. Does not conditionally return `null` or `undefined` when rendered on the server.
3. If using multiple JSX frameworks at the same time (e.g. React + Preact), pass the correct `include`/`exclude` options to integrations.
client:only="react" に変えるとビルドが通りました。3番目にあるとおり、React と Preact を同じプロジェクトで使うときは、手元のように react({ include: ['**/react/*'] })・preact({ include: ['**/preact/*'] }) と担当のフォルダーを分けます。
エラーにならないつまずき
- 1client:* を付け忘れてボタンが動かないエラーは出ない。手元でも押して「いいね 0」のままだった
- 2.astro の onclick={関数} が動かない出力は onclick="() => console.log(...)" という文字列。<script> で addEventListener を書く
- 3下書きが公開される一覧で除いても、getStaticPaths で除かないと個別ページが出力された
- 4client:media の画面で動かない条件に合わない幅では JS が読み込まれない。CSS で隠すだけなら client:visible が公式のすすめ
- 5Astro 7 に上げたらビルドが止まるRust 製コンパイラーは閉じていないタグなど不正な HTML に厳しい(公式の移行ガイド)
Vite の設定(エイリアス・環境変数など)は Astro の中でも同じ考え方です。関連記事「vite.configの書き方|用途別コピペ一覧とVite 8の変更点」で扱っています。
Astroのデプロイ(公開)の方法
この節では、作ったサイトをどこに公開できるかと、静的とオンデマンドでの違いが分かります。
静的な出力なら、npm run build でできた dist/ をそのまま置けるホスティングならどこでも公開できます。 公式ドキュメントのデプロイのページには、33のホスティングの手順があり、ビルドのコマンドは astro build(または npm run build)、公開するフォルダーは dist と書かれています。
| 出力 | 必要なもの | 公開先の例(公式の手順あり) |
|---|---|---|
| 静的(既定) | dist/ を置ける場所だけ | GitHub Pages・GitLab Pages・Netlify・Vercel・Cloudflare・S3 など |
| 一部オンデマンド・server:defer | アダプター(@astrojs/node など) | Netlify・Vercel・Cloudflare・Node.js が動くサーバー |
- Node.js のアダプターの
standaloneでは、node dist/server/entry.mjsでサーバーが起動しました。ホストとポートは環境変数HOST・PORTで変えられました。 - Git のリポジトリーと連携すると、コミットのたびに自動でビルドと公開を行えます(公式)。
公開の手順は、関連記事「GitHub Pagesとは|使い方・公開3通り・独自ドメインと404の直し方」と関連記事「Netlifyとは|使い方・料金・デプロイ方法とエラー対処を実例で」で扱っています。
よくある質問
Q. Astroとは何ですか? A. コンテンツ中心のサイトを速く作るための Web フレームワークです。ページをビルド時に HTML として書き出し、既定ではブラウザに JavaScript を送りません。動きが要る部品だけをアイランドとして動かします。
Q. Astroは無料ですか? A. 無料です。MIT ライセンスのオープンソースで、2026年1月に開発元が Cloudflare に加わったあとも、オープンソース・MIT ライセンスのまま続けると公式ブログに書かれています。
Q. Astroは何の言語で書きますか? A. HTML に近い .astro ファイルに、JavaScript か TypeScript を組み合わせて書きます。記事は Markdown や MDX でも書けます。Astro は言語ではなく、フレームワークです。
Q. Reactを知らなくても使えますか? A. 使えます。.astro と <script> だけで、手元のボタンも JS ファイルなしで動きました。React・Vue・Svelte などは、使いたくなったときに足せます。
Q. AstroでReactは使えますか?
A. 使えます。npx astro add react で追加し、部品に client:load などを付けます。付けなければ、React の部品も HTML として描かれるだけで JS は送られません。
Q. client:load と client:visible はどちらを使えばよいですか?
A. 開いてすぐ使う部品(ページ上部の検索窓など)は client:load、スクロールしないと見えない部品は client:visible が向いています。手元では client:visible の JS はスクロールするまで1つも読み込まれませんでした。
Q. AstroとNext.jsはどちらが速いですか? A. 手元の記事一覧では、Astro の JS は0バイト、Next.js 16 は約115KB(brotli)でした。読ませるページでは Astro の方が送る量が少なくなります。アプリのようにページ間で状態を持つ画面では、Next.js のルーターが役立ちます。
Q. AstroでSSR(サーバーサイドレンダリング)はできますか?
A. できます。アダプター(Node.js・Netlify・Vercel・Cloudflare)を入れ、ページに export const prerender = false を書くと、そのページだけリクエストのたびに描かれます。全ページを SSR にするなら output: 'server' にします。
Q. WordPressの代わりになりますか? A. 記事の表示だけなら Markdown と Content Collections で作れます。管理画面から記事を書く仕組みは Astro に無いため、ヘッドレス CMS と組み合わせるか、Markdown を Git で管理する運用にします。
Q. 必要なNode.jsの版はいくつですか? A. 2026年10月29日時点の Astro 7.4.4 は、Node.js 22.23.4 以上です。公式は v23 のような奇数の版は対象外としています。
Q. npm create astro が止まります。
A. Template ... could not be found! と出るなら、GitHub からテンプレートを取れていません。回線やプロキシを確かめるか、npm install astro から始める手動インストールで作れます。
まとめ
- Astro は、ページを HTML として書き出し、client:* を付けた部品(アイランド)にだけ JS を送る Web フレームワーク。ブログ・ドキュメント・企業サイトに向く。
- Astro 7.4.4 で作ったブログは、記事一覧も記事ページも JS が0バイトだった。React の島1つで約59.8KB、Preact なら約7.0KB(brotli)。同じ画面の Next.js 16 は約115KB。
- Markdown の記事は Content Collections で型付きにでき、フロントマターの誤りはビルドで、項目名の書き間違いは astro check で見つかった。
- アダプターを入れると、
prerender = falseのページだけを SSR にでき、server:deferでページの一部だけを後から描ける。 - テンプレートが取れないときは手動インストールで作れる。client:* の付け忘れ・下書きの出力・window の参照は、エラーの原文と節の表で確かめる。
参考・出典
確認日はいずれも 2026年10月29日です。
- Astro Docs「Why Astro?」:https://docs.astro.build/ja/concepts/why-astro/
- Astro Docs「Install Astro」:https://docs.astro.build/en/install-and-setup/
- Astro Docs「Islands architecture」:https://docs.astro.build/ja/concepts/islands/
- Astro Docs「Template directives reference」:https://docs.astro.build/en/reference/directives-reference/
- Astro Docs「Content collections」:https://docs.astro.build/en/guides/content-collections/
- Astro Docs「On-demand rendering」:https://docs.astro.build/en/guides/on-demand-rendering/
- Astro Docs「CLI Commands」:https://docs.astro.build/en/reference/cli-reference/
- Astro Docs「Upgrade to Astro v7」:https://docs.astro.build/en/guides/upgrade-to/v7/
- Astro Docs「Deploy your Astro Site」:https://docs.astro.build/en/guides/deploy/
- Astro Blog「The Astro Technology Company joins Cloudflare」:https://astro.build/blog/joining-cloudflare/
- npm「astro」:https://www.npmjs.com/package/astro
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Astroとは・使い方入門|JSゼロのブログをNext.jsと実測比較」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。