AstroのSEO
AstroはSEOに強いフレームワークの1つです。デフォルトではページを静的HTMLにプリレンダリングし、指定した場所だけJSを送るため、強いCore Web Vitalsが期待できます。ただしデフォルトは保証ではなく、metaタグ、サイトマップ、canonicalは自動生成されません。私が自分のAstroサイトをどう運用しているか、適切なアーキテクチャをどう作るかを解説します。
言語
AstroがSEOに強いフレームワークの選択肢である理由は、デフォルトで静的HTMLへプリレンダリングするためです。最初のクロールで生HTMLにコンテンツがあり、そのルートではレンダリングキューを待ちません。Islandsはclientディレクティブを付けたコンポーネントだけをハイドレーションするため、ページの大部分は専用のハイドレーションJSなしで配信されます(Astroは別の場所でページスクリプトやルーターJSを追加できます)。ただし、これだけでクロール可能性、インデックス登録、順位は保証されないため、デプロイ済みルートを確認します。Astroサイトは強いCore Web Vitalsの数字も出します。注意点は、きれいなHTMLを生成してもmetaタグ、canonical、サイトマップ、構造化データは書かないことです。これらは明示的なビルド手順であり、サイトマップの検出対象は静的生成ルートなので、ランタイム専用URLには明示的な処理が必要です。アダプターが必要なServer IslandsとView Transitionsは、クローラーが実際に取得するものを理解すればSEOに安全です。私はpatrickstox.comをAstroで運用しており、これが実際に使っているスタックです。
TL;DR — AstroはSEOにとてもよい選択です。デフォルトでは、ページをあらかじめプレーンなHTMLファイルに変換するため、Google(またはどのボット)が訪れたときにはコンテンツがすでにあります。JavaScriptの実行を待つ必要がありません。速度も非常に速いです。知っておくべき点は1つです。AstroはきれいなHTMLを提供しますが、ページのtitle、サイトマップ、canonicalタグは自動では追加しません。自分で設定します(難しくありません)。
「Astro SEO」とは
Astroはウェブサイトを作るためのウェブフレームワークです。大きな考え方は「JavaScriptを減らす」ことです。ReactやNext.jsのようなフレームワークがJavaScriptを使ってブラウザー内でページを構築することが多いのに対し、Astroはページをビルド時にプレーンなHTMLファイルへ変換し、ページの一部が実際に必要とする場合を除いて、ほとんどJavaScriptを送信しません。 Evidence for this claim Astro prerenders pages as static HTML by default and only sends client JavaScript for explicitly hydrated components. Scope: Astro default static output and islands architecture. Confidence: high · Verified: Astro: Why Astro
この1つの違いが、Astroを検索エンジンにとって扱いやすくします。検索エンジンがページをクロールするとき、コンテンツを読み取りたいと考えます。JavaScriptの多いサイトでは、ページにコンテンツがまだないことがあり、ボットは先にJavaScriptを実行しなければならず、遅れる可能性があります。Astroでは、ページが読み込まれた瞬間からコンテンツがHTMLにあります。待つものがありません。
私は自分のサイトpatrickstox.comをAstroで運用しています。これは理論ではなく、実際に使っているスタックです。
AstroがSEOに適している理由
- コンテンツがすぐHTMLにある。 レンダリングの遅延も、コンテンツの欠落もありません。
- 速い。 Astroのサイトは軽量で、Googleのページエクスペリエンス指標(Core Web Vitals)で非常によいスコアになりやすいです。
- 各ページが実在する固有URLを持つ。 クローラーを混乱させる可能性がある複雑なシングルページアプリのルーティングはありません。
- JavaScriptは必要な場所だけ読み込む。 フォトギャラリーや検索ボックスをインタラクティブにしながら、ページの残りを遅くせずに済みます。
Astroがしてくれないこと
ここで混乱する人がいます。「AstroはSEOに最適化されている」は半分だけ正しい表現です。Astroはきれいな基盤を提供しますが、次のものを自動では行いません。
- ページのtitleとmeta descriptionを書く。
- サイトマップを生成する(公式の無料プラグインを追加します)。 Evidence for this claim Astro's official sitemap integration generates sitemap files from statically generated routes. Scope: Astro @astrojs/sitemap integration. Confidence: high · Verified: Astro: Sitemap integration
- canonicalタグを追加する(ページの「公式」バージョンをGoogleに伝えるタグ)。
- 構造化データを追加する(リッチリザルトを支えるコード)。
- robots.txtファイルを作成する。
どれも難しくありません。自分で設定するだけです。Astroをすばらしいキッチンだと考えてください。調理器具は優れていますが、料理は自分で作る必要があります。
簡単なスターターチェックリスト
- 公式の
@astrojs/sitemapプラグインでサイトマップを追加する。 - すべてのページに
title、description、canonicalURLを設定する(通常は共有レイアウトファイルから設定)。 - 写真にはAstro組み込みの
<Image />コンポーネントを使う。画像が速く読み込まれ、ページのガタつきも防げます。 robots.txtファイルをpublic/フォルダーに置く。
Server Islands、View Transitions、静的レンダリングとサーバーレンダリング、避けるべき正確なミスまで含む詳しい版を読みたい場合は、Advancedタブに切り替えてください。検索エンジンがJavaScriptを扱う全体像は、JavaScript SEOを参照してください。
Evidence for this claim Astro prerenders pages as static HTML by default and only sends client JavaScript for explicitly hydrated components. Scope: Astro default static output and islands architecture. Confidence: high · Verified: Astro: Why AstroTL;DR — AstroはSEO向けにアーキテクチャがよく整っています。デフォルトではページとエンドポイントが静的HTMLにプリレンダリングされるため、そのコンテンツについてレンダリングキューの波を待つ必要がありません。ただしこれはデフォルトであって、すべてのルートに共通する保証ではありません。静的/サーバーHTMLだけで本番URLのクロール可能性、インデックス登録、順位、Core Web Vitalsが証明されるわけでもありません。Islandsアーキテクチャは
client:*ディレクティブを付けたコンポーネントだけをハイドレーションします。それ以外は専用のハイドレーションJSなしでHTMLを送りますが、ページスクリプト、他のIsland、ルーター拡張がページの別の場所にJavaScriptを追加することはあります。Astroはmetaタグ、canonical、サイトマップ、構造化データを自動生成しません。Content CollectionsとZodで検証しながら、明示的に接続します。アダプターが必要なServer Islandsは初期ドキュメントにフォールバックコンテンツ付きの静的シェルを返し、遅延コンテンツを後から独立して取得します。クローラーが実際に何を取得するかを確認してください。View Transitionsはhistory.pushStateを使うためSEOに安全で、Googleは基礎にあるMPAページを通常どおりクロールします。私はpatrickstox.comをAstroで運用しており、以下はローカル開発だけでなくデプロイ済みサイトで検証して実際に使っている機能です。
AstroがJavaScriptレンダリングの問題を完全に回避する理由
JavaScript SEOが難しい理由は、2回目の波にあります。Googleはまず生HTMLを取得し、その後ヘッドレスChromiumでレンダリングするためにページをキューへ入れます。このキューがリスクです。Google自身のドキュメントにはこうあります。“Googlebot queues all pages with a 200 HTTP status code for rendering unless a robots meta tag tells Google not to index the page. The page may stay on this queue for a few seconds, but it can take longer than that.” (翻訳)(robots metaタグがページをインデックス登録しないようGoogleに伝えない限り、GooglebotはHTTPステータスコード200のすべてのページをレンダリング用にキューへ入れます。ページは数秒このキューに留まることがありますが、それより長くなる場合もあります。)クライアントレンダリングのSPAでは、そのレンダリング波が動くまでコンテンツが存在しません。
Astroのデフォルト出力モードはstaticです。ページとエンドポイントはビルド時に完全なHTMLファイルへプリレンダリングされます。したがって、そのデフォルトで動くルートでは、生HTML自体がレンダリング済みページです。 Evidence for this claim Astro uses static output and prerenders routes at build time by default. Scope: Astro default output mode; routes can opt out of prerendering. Confidence: high · Verified: Astro: On-demand rendering 実行するものが残っていないため、そのルートで2回目の波を待つ必要はありません。Googlebotは最初の取得で完全なコンテンツを見ます。Yoast創業者のJoost de Valkの言葉では、“From an SEO perspective, static HTML on a CDN is a better starting point than most CMSes will ever give you.” (翻訳)(SEOの観点では、CDN上の静的HTMLは、ほとんどのCMSが提供できるものよりも優れた出発点です。)
ただし、これはデフォルトです。すべてのルートに共通する性質ではありません。output: 'server'を設定すると、デフォルトはオンデマンドレンダリングへ切り替わります(詳しくは後述)。静的デフォルトのプロジェクトでも、アダプターを使えば個々のルートがexport const prerender = falseでオプトアウトできます。アーキテクチャだけで何かが保証されるわけではありません。静的/サーバーHTML、Island、アダプターだけでは、クロール可能性、インデックス登録、順位、Core Web Vitalsは保証されません。デプロイされたルートと個々のクローラーに依存するため、フレームワークが処理すると決めつけず検証します。
これは、まったくレンダリングできないクローラーにも役立ちます。Googleは*“not all bots can run JavaScript”* (翻訳)(すべてのボットがJavaScriptを実行できるわけではありません。)と明確に述べています。これは2026年の現実で、ほとんどのAIクローラーや多くのサードパーティーツールに当てはまります。AstroのHTML優先出力は、実際にプリレンダリングされた場所ではGooglebotだけでなく、すべてのクローラーが読めます。(これはSEO for a headless CMSで述べているのと同じ点です。レンダリングモードが製品そのものです。)
Islandsアーキテクチャ:求めた場所だけJSを使う
AstroはコンポーネントをHTMLへレンダリングし、言葉どおり「just HTML & CSS, stripping out all client-side JavaScript automatically」を送ります。インタラクティブ性はオプトインです。client:*ディレクティブ(client:load、client:idle、client:visible)をコンポーネントに付けると、そのIslandだけがJavaScriptでハイドレーションされます。それ以外は静的HTMLのままです。 Evidence for this claim Astro client directives selectively hydrate interactive islands while other components remain static HTML. Scope: Astro islands and client directives. Confidence: high · Verified: Astro: Islands
SEOにとっては理想に近い構成です。Googlebotがインデックス登録する必要があるコンテンツはプレーンHTMLで、インタラクティブなウィジェットがページを重くしません。client:visibleは特に便利です。ページ下部のコンポーネントは、スクロールして見えるまでハイドレーションを始めないため、LCPをブロックしません。この概念はPreactの作者Jason Millerが提唱したもので、“rendering HTML pages on the server, and inject[ing] placeholders or slots around highly dynamic regions” (翻訳)(サーバーでHTMLページをレンダリングし、動的な領域の周囲にプレースホルダーまたはスロットを挿入すること)と説明しました。
競合の説明が混同しがちな、正確に区別すべき2つの注意点があります。
client:onlyは別物です。client:load/client:idle/client:visibleと違い、client:onlyコンポーネントはサーバーレンダリングを完全に省略し、サーバー上ではHTMLをまったく生成しません。client:onlyの内部だけに置いたインデックス登録対象のコンテンツは、Googlebotが取得するドキュメントに存在せず、ブラウザーがハイドレーションした後にだけ存在します。主要コンテンツを置かないでください。- これは選択的ハイドレーションであり、レジューム可能性ではありません。 Astroはブラウザーで各Islandのクライアントコードを最初から再実行します。Qwikのようなレジューム可能性モデルがサーバーでシリアライズした実行状態を再開する仕組みではありません。記事では混同されますが、同じメカニズムではありません。
ハイドレーションされないコンポーネントだけで、ページ上のJavaScriptの全体像が決まるわけでもありません。「Zero JS」とはclient:*ディレクティブのない1つのコンポーネントを説明する言葉です。Astroはページレベルの<script>タグ、View Transitionsルーター、ページ上の別のIslandを送ることがあります。ページ全体についての一括した主張ではなく、コンポーネント/ルートごとに何が送られるかを説明してください。
Astroが自動ではしないこと
Astroは意味のあるきれいなHTMLを生成しますが、SEOに関してはそれだけです。メタデータ、canonical、サイトマップ、構造化データは初期状態ではありません。「Astroは自動的にSEO最適化される」という神話は、そのまま神話です。自分で設定するものは次のとおりです。
- Metaタグ(title、description、Open Graph、Twitter)
- Canonical URL
- サイトマップ(公式インテグレーション経由)
- 構造化データ/JSON-LD
- robots.txt
Astroは私が使った中で最良の基盤ですが、基盤であって完成した家ではありません。
サイトマップ:@astrojs/sitemap
npx astro add sitemapでインストールします。静的に生成されたルートをクロールし、ビルド時にsitemap-index.xmlと分割されたsitemap-0.xmlファイルを出力します。2つの点でつまずく人がいます。
astro.config.mjsにsite:を設定する必要があります。 設定しないと、インテグレーションは何も生成せずに静かに終わります。「サイトマップはどこ?」の原因として最も多いものです。robots.txtにサイトマップの行を自分で追加する必要があります。 Astroは行を追加しません。
制御するには、filter()でルート(プレビュー/下書きページなど、このサイトでまさに使っているもの)を除外し、serialize()でlastmod/changefreq/priorityを設定し、i18nオプションでサイトマップにhreflangエントリを出力します。これは現在の@astrojs/sitemapドキュメントの仕様です。古いリリースを使っている場合はインストール済みのバージョンで確認してください。インテグレーションの動作は過去にメジャーバージョン間で変わっています。
人がつまずく範囲: インテグレーションの検出対象は静的に生成されたルートです。URLがランタイムにしか存在しない場合、サーバーレンダリング(output: 'server')のルートやビルド時ではなくオンデマンドで生成されるルートがサイトマップに入ると決めつけないでください。customPagesで明示的に追加し、ビルド後にsitemap-index.xmlを実際に開いて存在を確認します。ビルド時の静的ルートでないものについて、「インテグレーションが処理する」と信じるだけでは不十分です。
Metaタグとcanonical:BaseLayoutパターン
Astroには特別な<Head>コンポーネントがありません。.astroファイルで<head>を直接制御します。標準的なパターン、そして私が使っている方法は、title、description、canonicalURLをpropsとして受け取りheadを書き出す単一のBaseLayout.astroです。すべてのページでcanonicalを明示し、og:urlと一致させます。ライブラリは不要ですが、コミュニティのastro-seoパッケージ(npm)は、title/description/OG/Twitter/canonicalを1つのコンポーネントで包む便利なラッパーです。
Content CollectionsをSEOの安全網にする
これはAstroの過小評価されているSEO機能です。Content Collectionsは、Markdown/MDX/JSON向けの型安全なコンテンツレイヤーで、Zodスキーマ検証を備えています。つまり、titleとdescriptionを必須フィールドにでき、ページにどちらかがなければビルドが失敗します。titleのないページを誤って公開できません。getCollection()やgetEntry()などのクエリ関数はビルド時に静的ページを生成するため、デプロイ時の出力はプレーンHTMLです。MDXが生のMarkdownを真実のソースとして保持するので、これらのファイルはAIクローラーやllms.txt形式のパターンにとってもきれいなソースコンテンツです。このサイト自体も、Zodでfrontmatterを検証するContent Collectionsで構築しています。
astro:assets:画像を正しく扱う(1つの落とし穴)
<Image />コンポーネントは自動的にWebPへ変換し、「Cumulative Layout Shift(CLS)を避ける」ために寸法を推測し、デフォルトでloading="lazy"を設定し、altを必須にします。altがないとコンパイルエラーになります。<Picture />はAVIF/WebP/フォールバックの<source>要素でこれを拡張します。
落とし穴は、デフォルトのloading="lazy"がLCP画像(通常はヒーロー画像)には不適切なことです。最も重要な画像を遅延読み込みすると、その画像の遅延が起きます。ファーストビューの画像ではloading="eager"とfetchpriority="high"で上書きします。リモート画像には明示的なwidthとheightが必要です。
Server Islands:クローラーが実際に見るもの
Server Islands(Astro 4,12以降)は、競合のガイドが最もよく間違える機能です。server:deferを使うと、コンポーネントはメインページとは独立してサーバー上でレンダリングされます。静的シェルはすぐに配信され、Astroのドキュメントによれば、“Your page will be rendered immediately with any specified fallback content as a placeholder. Then, the component’s own contents are fetched on the client and displayed when available.” (翻訳)(指定したフォールバックコンテンツをプレースホルダーとして、ページはすぐにレンダリングされます。その後、コンポーネント自身の内容がクライアントで取得され、利用可能になった時点で表示されます。)となります。
正確に説明すべき点が2つあります。第一に、Server Islandsにはアダプターが必要です。純粋な静的ビルドが単独で生成するものではなく、オンデマンド機能です。第二に、流れはこうです。初期ドキュメントには設定したフォールバックコンテンツが含まれ、Islandの実コンテンツはページ読み込み後に独自のエンドポイントから別の独立したリクエストで取得されます。これは最初のドキュメントに含まれる内容の明確な下限です。自分のデプロイ済みURLを直接テストせずに、各クローラーが次に何をするかを一般化しないでください。
SEO上の影響は具体的です。最初の取得でクローラーが読む静的HTMLに含まれるのは、遅延Islandのコンテンツではなくフォールバックコンテンツです。 これはServer Islandsの目的である、キャッシュやインデックス登録を避けるべき個人化・セッション固有の情報(ログイン状態、カート数、レコメンド)には最適です。主要なインデックス登録対象コンテンツには不適切です。順位が必要なものはメインのAstroテンプレートに置き、Server Islandsには周囲の動的な部分だけを任せてください。
出力モード:staticとserver、ルートごとの上書き
Astroのデフォルト出力モードはstaticです。ページとエンドポイントはビルド時にHTMLへプリレンダリングされます。astro.config.mjsでoutput: 'server'を設定するとデフォルトはオンデマンドレンダリングになり、アダプターを使ってリクエストごとにページを描画します。Server Islandsでは足りない認証、リアルタイムデータ、個人化に役立ちます。どちらのモードでも、ルートごとにデフォルトを上書きできます。静的デフォルトのプロジェクトではexport const prerender = falseでオンデマンドに、サーバーデフォルトのプロジェクトではexport const prerender = trueでビルド時のプリレンダリングに戻せます。「サイトは静的」「サイトはSSR」という説明がすべてのルートに当てはまることはほとんどありません。トップレベルの設定だけでなく、ルートごとの設定を確認します。
純粋なSEOの観点では、プリレンダリングHTMLとオンデマンドHTMLは同等です。実際にルートが完全なマークアップ付きで200を返すことを確認できれば、どちらもクローラーの最初のリクエストに完全なHTMLを返します。オンデマンドのルートはHTMLをストリーミングでき、遅いデータやネットワーク状況で後続チャンクが遅れることがあるため、ストリーミングレスポンスはすべてのコンテンツが届いた証明にはなりません。確認してください。2つのモードの本当の違いは運用です。プリレンダリングコンテンツは次のビルド(または別途設定したランタイム更新)まで固定され、CDNエッジから直接配信されます。オンデマンドコンテンツは常に最新ですが、本番でアダプターとランタイムが正常であることに依存します。SEOの選択とは考えず、データの新しさと運用で選び、ローカル開発で動いたことから推測せずに、デプロイ済みルートのステータス、リダイレクト、レスポンスヘッダーを検証します。
View Transitions:SPAのように見えてもSEOに安全
Astroの<ClientRouter />(以前の<ViewTransitions />)は、ブラウザーのView Transitions APIとHistory APIを使ってSPAのようなソフトナビゲーションを提供します。重要なのは、history.pushStateで移動することです。これはGoogleがクライアント側ナビゲーションに推奨している方法です。Googleはフラグメントベース(#hash)のURLを「can’t reliably resolve」と警告しています。重要なのは、View Transitionsがブラウザー側の拡張であることです。Googlebotがクロールするときは各URLをリクエストし、通常の完全なHTMLページを取得します。下にあるMPAは変わりません。トランジションが変えるのはブラウザーで人間が見るものだけです。
したがって、View TransitionsがAstroサイトをSPAに変えたり、SEOを壊したりするわけではありません。注意すべき空白は、AstroのView TransitionsドキュメントにSEOのセクションがないことです。そのため「SEOを壊す」という神話が残っているのでしょう。自分のサイトで確認するには、いくつかのURLを直接取得して、それぞれが完全なHTMLを返すことを確認してください。思い込みで済ませず、自分のデプロイを確認します。
よくあるAstro SEOのミス
- AstroがSEOを処理してくれると思う。 Astroが処理するのはHTMLです。Meta、canonical、サイトマップ、schemaは自分で設定します。
- 設定で
site:を忘れる。 サイトマップが静かに生成されません。 - robots.txtにサイトマップを追加しない。 Astroは追加しません。
- LCP画像を遅延読み込みする。 ヒーロー画像を
eagerとfetchpriorityで上書きします。 - インデックス登録対象コンテンツをServer Islandに置く。 クローラーが見るのはフォールバックで、そもそもServer Islandsにはアダプターが必要です。
- 完璧なLighthouseスコアを追いかけて止まる。 速度は順位シグナルの1つであり、唯一の順位シグナルではありません。速くても空のページは順位が上がらず、コンテンツ、リンク、E-E-A-Tが引き続き大きな役割を果たします。
- インデックス登録対象コンテンツを
client:onlyコンポーネントの中だけに置く。 他のclient:*ディレクティブと違って、client:onlyはサーバーレンダリングを完全に省略するため、ブラウザーがハイドレーションするまでそのコンポーネントのHTMLはありません。 - 「Astroは静的/高速」を成果の保証として扱う。 静的またはオンデマンドHTML、Island、アダプターは仕組みです。それだけでクロール可能性、インデックス登録、順位、Core Web Vitalsを保証しません。アーキテクチャ図ではなく、デプロイ済みルートを検証してください。
このトピッククラスターでの位置付け
Astroは、JavaScript SEOが提起するレンダリングの問いに対する、具体的で特にSEOに強い答えの1つです。また、headless CMS構成で人気のフロントエンドでもあります。パフォーマンスの側面はウェブパフォーマンスクラスターのCore Web Vitalsに直接つながり、「コンテンツが実際にHTMLにあるか」をテストする習慣はクロールとインデックス登録のクラスターと同じです。
Astro SEOのアンチパターン
Astroのサイトで実際に見かける具体的なミスです。仮定の話ではありません。どれも診断ではなく予防のためのものです。公開前に見つけてください。
Astroを初期状態で「SEO最適化済み」と扱う
Astroは高速でクリーンな静的HTMLを提供し、それは確かに大きな先行優位ですが、metaタグ、canonical、サイトマップ、構造化データと同じではありません。なぜ間違いか: チームが「AstroがSEOを処理する」と考え、<title>の変化もcanonicalもサイトマップもないページを公開し、期待どおりにインデックス登録されない理由を不思議に思います。代わりにすること: 最初からtitle/description/canonical用のBaseLayout.astro propsを接続し、@astrojs/sitemapを追加し、それらをデフォルトではなく必須のビルド手順として扱います。
astro.config.mjsでsite:を忘れる
これは「なぜサイトマップが空なのか」という報告で最も多いものです。なぜ間違いか: @astrojs/sitemapは絶対的な<loc>エントリを作るために絶対サイトURLを必要とします。site:を設定しないと、インテグレーションは静かに何も生成しません(エラーも警告もありません)。代わりにすること: サイトマップインテグレーションをインストールする前にastro.config.mjsへsite:を設定し、次のビルド後にsitemap-index.xmlへ実際にURLが入っていることを確認します。
サイトマップをrobots.txtから抜かす
@astrojs/sitemapをインストールしても、robots.txtにSitemap:行は追加されません。自動だと思っている人が多い、別の手動手順です。なぜ間違いか: Search Consoleで送信すれば検索エンジンはサイトマップを見つけられますが、他のボット(Bing/IndexNowに隣接するクローラーなど)が頼る受動的な発見経路を失います。代わりにすること: public/のrobots.txtにSitemap: https://yoursite.com/sitemap-index.xml を追加し、デプロイ後に解決することを確認します。
ヒーロー画像にデフォルトのloading="lazy"を残す
Astroの<Image />コンポーネントはデフォルトで遅延読み込みします。これはファーストビューより下の画像には正しく、通常LCP要素になる1枚の画像には不適切です。なぜ間違いか: ヒーローを遅延読み込みすると、ブラウザーがその画像のリクエストを開始すること自体が遅れ、Largest Contentful Paintのスコアに直接悪影響を与えます。代わりにすること: ヒーロー/ファーストビューの画像だけはloading="eager"とfetchpriority="high"で明示的に上書きし、それ以外はlazyのデフォルトにします。
インデックス登録対象コンテンツをServer Islandの中に置く
server:deferは個人化されたセッション固有のコンテンツ(カート数、ログイン状態、レコメンド)向けであり、順位が必要なもの向けではありません。なぜ間違いか: クローラーが読む静的HTMLに含まれるのは、ページ読み込み後にクライアント側で取得される内容ではなく、Islandに指定したフォールバックコンテンツです。そこに主要コンテンツを置くと、最初のクロールで検索エンジンから見えません。代わりにすること: 順位が必要なコンテンツはメインのAstroテンプレートに残し、インデックス登録すべきでない動的な個人化部分だけにServer Islandsを使います。
高いLighthouseスコアをゴールと考える
Astroのサイトはほぼデフォルトで強いCore Web Vitalsを出すため、そこで止めたくなります。なぜ間違いか: 速度は多くの順位入力の1つです。速くても空または薄いページは、よりよいコンテンツ、リンク、トピックの深さを持つ遅いページより上位にはなりません。代わりにすること: パフォーマンスはAstroから無料で得られる土台と考え、実際の最適化作業はコンテンツ品質、内部リンク、Astroが行わない構造化データ/meta作業に使います。
「デフォルトでstatic」がすべてのルートに当てはまると考える
Astroの静的出力モードはデフォルトですが、普遍的な性質ではありません。output: 'server'で切り替わり、prerenderはルートごとにどちらの方向にも設定できます。なぜ間違いか: トップレベルの設定だけでサイト全体を「static」または「SSR」と説明し、個々のルートを確認しないため、本番で1つのルートだけ挙動が違って驚きます。代わりにすること: 考えている対象のルートでprerender設定を確認し、設定ファイルではなくデプロイ済みURLの実際のレスポンス(ステータスコード、完全なマークアップ、リダイレクト動作)を検証します。
コンテンツをclient:onlyコンポーネントの中だけに置く
client:onlyはclient:load/client:idle/client:visibleと同じではなく、サーバーレンダリングを完全に省略します。なぜ間違いか: client:onlyを使うコンポーネントはサーバー上でHTMLを生成しないため、そこだけに置いたインデックス登録対象コンテンツは生レスポンスを読むクローラーから見えません。「簡単だから」とSEOコストに気付かずclient:onlyを選びやすい点も問題です。代わりにすること: 主要コンテンツはサーバーレンダリングされるコンポーネントまたはページテンプレートに置き、インデックス登録対象を含まない操作専用ウィジェットだけにclient:onlyを使います。
AIによる要約
Advanced版を簡潔にまとめると、次のとおりです。
- Astroのデフォルト出力モードはビルド時に静的HTMLへプリレンダリングする。 そのデフォルトで動くルートでは、生HTMLが完成したページです。そのためGoogleのレンダリングキュー(「2回目の波」)の問題は適用されません。ただしこれは普遍的な性質ではなく、
output: 'server'で切り替わり、prerenderでルートごとに上書きできます。 - Islandsアーキテクチャは
client:*を付けたコンポーネントだけをハイドレーションします。付けていないコンポーネントは専用のハイドレーションJSなしでHTMLを送ります(Astroはページスクリプト、他のIsland、ルーターJSをページの別の場所に追加できます)。client:onlyは例外で、サーバーレンダリングを完全に省略するため、インデックス登録対象コンテンツをそこだけに置くべきではありません。これは選択的ハイドレーションでありレジューム可能性ではありません。client:visibleはファーストビューより下のJSがLCPをブロックするのを防ぎます。 - AstroはSEOに関して何も自動生成しない。 metaタグ、canonical、サイトマップ、構造化データ、robots.txtはすべて明示的なビルド手順です。「Astroは自動SEO最適化」というのは神話です。
- **
@astrojs/sitemap**は静的に生成されたルートを検出します。ただし設定にsite:を指定し(指定しないと静かに何もしません)、robots.txtのサイトマップ行を自分で追加し、ランタイム専用URLはcustomPagesで明示的に追加する必要があります。 - Content Collections + Zodは
title/descriptionを必須にでき、ページにないとビルドを失敗させるSEOの安全網です。 - **
astro:assetsの<Image>**はWebPへ変換し、寸法を設定してCLSを防ぎ、デフォルトで遅延読み込みし、altを必須にします。LCP画像はloading="eager"+fetchpriority="high"で上書きします。 - Server Islands(
server:defer)にはアダプターが必要で、初期ドキュメントでは静的シェルとフォールバックをすぐに返し、その後Islandを独立して取得します。最初のドキュメントを読むクローラーが見るのはIslandではなくフォールバックです。インデックス登録対象コンテンツをそこに置かないでください。 - 静的出力とオンデマンド(server)出力は、検証済みならSEO上同等です。 どちらも最初のリクエストで完全なHTMLを返しますが、オンデマンドのルートはストリーミングできるため、レスポンスが完全に届くことを確認します。モードはSEOではなくデータの新しさと運用で選びます。
- **View Transitions(
<ClientRouter />)**はhistory.pushStateを使いSEOに安全です。Googleは基礎にあるMPAページを通常どおりクロールします。ブラウザー側の拡張であり、SPAへの変換ではありません。 - 上記のいずれも成果の保証ではない。 静的/サーバーHTML、Island、アダプターは仕組みであって、クロール可能性、インデックス登録、順位、Core Web Vitalsの証明ではありません。デプロイ済みルートを検証します。
- Astroは自身の2023年ベンチマークで強いCore Web Vitalsの数字を出している。 Astroサイトの50%超がGoogleのCWV評価に合格し、当時の業界ベースラインを大きく上回りました。現在の保証ではなく、日付のあるデータ点として扱います。
公式ドキュメント
Astroと検索エンジンによる一次資料のドキュメントです。
Astro
- Islands Architecture — Astroがクライアント側JSを取り除き、インタラクティブなコンポーネントだけをハイドレーションする方法。
- Template Directives Reference —
client:load/idle/visible/onlyとserver:defer、およびclient:onlyが省略するもの。 - Image Optimization (astro:assets) —
<Image>/<Picture>、WebP、寸法、CLS。 - @astrojs/sitemap — 自動サイトマップ生成、
filter、serialize、i18n。 - Server Islands —
server:defer、アダプター要件、フォールバックコンテンツ、遅延したクライアント取得。 - On-Demand Rendering —
static/server出力モード、ルートごとのprerender、HTMLストリーミング。 - Routing Reference — ページとエンドポイントがデフォルトでプリレンダリングされる方法。
- Astro Runtime API Reference —
Response/リダイレクト処理とデフォルトステータスコード。 - Content Collections — Zodスキーマ検証付きの型安全なコンテンツ。
- View Transitions —
<ClientRouter />とHistory APIナビゲーション。
- Understand JavaScript SEO Basics — レンダリングキュー、クロール可能なリンク、History API、「すべてのボットがJavaScriptを実行できるわけではない」という注意。
- In-Depth Guide to How Google Search Works — クロール→レンダリング→インデックス登録と、SSGがレンダリング手順をなくす場所。
Bing/Microsoft
- IndexNow/indexnow.org — 静的Astroデプロイと相性のよいプッシュプロトコルです。公開手順に接続して、BingとYandexへ新しいページをすぐ知らせます。
出典からの引用
Astroのドキュメント、Google、名前のある実務家による記録に残る発言です。検索エンジンとドキュメントの各リンクは、出典ページの引用箇所へ移動するディープリンクになっています。
Google — Astroが回避するレンダリングキュー
- “Googlebot queues all pages with a 200 HTTP status code for rendering unless a robots meta tag tells Google not to index the page. The page may stay on this queue for a few seconds, but it can take longer than that.” (翻訳)(robots metaタグがページをインデックス登録しないようGoogleに伝えない限り、GooglebotはHTTPステータスコード200のすべてのページをレンダリング用にキューへ入れます。ページは数秒このキューに留まることがありますが、それより長くなる場合もあります。) 引用へ移動
- “not all bots can run JavaScript” (翻訳)(すべてのボットがJavaScriptを実行できるわけではありません。) — HTML優先の出力がGooglebot以外にも役立つ理由です。 引用へ移動
Astroのドキュメント — Island、画像、サイトマップ、Server Islands
- “just HTML & CSS, stripping out all client-side JavaScript automatically.” (翻訳)(HTMLとCSSだけで、クライアント側のJavaScriptを自動的に取り除きます。) — Islandsアーキテクチャについて。 引用へ移動
- “infers image dimensions to avoid Cumulative Layout Shift (CLS).” (翻訳)(Cumulative Layout Shift(CLS)を避けるために画像の寸法を推測します。) — Imageコンポーネントについて。 引用へ移動
- “Your page will be rendered immediately with any specified fallback content as a placeholder. Then, the component’s own contents are fetched on the client and displayed when available.” (翻訳)(指定したフォールバックコンテンツをプレースホルダーとして、ページはすぐにレンダリングされます。その後、コンポーネント自身の内容がクライアントで取得され、利用可能になった時点で表示されます。) — Server Islandsについて。 引用へ移動
Jason Miller(Preactの作者、「islands architecture」という言葉を作った人物)
- 選択的ハイドレーションは、“rendering HTML pages on the server, and inject[ing] placeholders or slots around highly dynamic regions.” (翻訳)(サーバーでHTMLページをレンダリングし、動的な領域の周囲にプレースホルダーまたはスロットを挿入します。)によって機能します。 — Astro Docs: Islands Architectureに引用されています。
Joost de Valk(Yoast SEOの創業者)
- “From an SEO perspective, static HTML on a CDN is a better starting point than most CMSes will ever give you.” (翻訳)(SEOの観点では、CDN上の静的HTMLは、ほとんどのCMSが提供できるものよりも優れた出発点です。) — Joost.blog: Astro SEO Complete Guide
Astro SEOチェックリスト
Astroサイトが検索向けに実際に設定されているかを確認するための手順です。よい基盤の上に置かれているだけでは不十分です。
-
astro.config.mjsにsite:を設定した(設定しないとサイトマップは静かに生成されない)。 -
@astrojs/sitemapをインストールし、サイトマップ参照をrobots.txtへ手動で追加した。-
public/にrobots.txtがあり、インデックス登録したいものをブロックしていない。 - すべてのページに固有の
titleとdescriptionを設定した(理想的には共有のBaseLayout.astro経由)。 - すべてのページに自己参照canonicalがあり、
og:urlと一致する。 - Content Collectionsが
title/descriptionを必須にするZodスキーマを使っている(欠落時はビルドが失敗する)。 - 画像に
<Image />/<Picture />を使い、すべてにaltがある(欠落はコンパイルエラーにもなる)。 - LCP/ヒーロー画像でデフォルトの遅延読み込みを
loading="eager"とfetchpriority="high"に上書きした。 - インデックス登録対象コンテンツをServer Island(
server:defer)に置いていない。クローラーはフォールバックを見て、Server Islandsにはアダプターが必要。 -
client:onlyコンポーネントの中だけにインデックス登録対象コンテンツを置いていない。サーバーレンダリングを省略するため、ブラウザーがハイドレーションするまでHTMLがない。 -
output: 'server'またはルートごとのprerender = falseを使うルートでは、ランタイム専用URLをサイトマップへ明示的に追加した(customPages)。自動サイトマップの検出対象は静的に生成されたルート。 - 構造化データ(JSON-LD)がサーバーレンダリングされる
<head>にある。 -
<ClientRouter />を有効にした場合、各URLが直接取得で完全なHTMLを返すことをサンプル確認した。 - オンデマンド/serverルートでは、本番URLを直接取得し、ステータスコード、リダイレクト動作、完全なレスポンスHTMLを確認した。ローカル開発から推測しない(アダプター/ランタイムは異なることがある)。
-
メンタルモデル
1. 生HTMLが完成したページ — そのルートのデフォルトでは。
Astroの静的出力モードでは、プリレンダリングされたルートに対してレンダリング波を待つ必要がありません。Googlebotが取得するものがインデックス登録されます。これはサイト全体の保証ではなくルートごとのデフォルトです(output: 'server'とルートごとのprerenderで変えられます)。適用される場合、View Sourceが真実です(CSR SPAとは逆)。ただし事実として扱う前に適用されることを確認してください。
2. 基盤であって完成ではなく、成果の保証でもない。 AstroはきれいなHTMLと強いパフォーマンスの仕組みを無料で提供します。検索エンジンへ意味を伝えるもの(meta、canonical、サイトマップ、schema)は、すべて自分で追加する明示的な手順です。「よいアーキテクチャ」≠「完了」であり、どちらもクロール可能性、インデックス登録、順位の証明ではありません。デプロイ済みサイトで検証する必要があります。
3. Islandは追加的 — ただしclient:onlyを除く。
client:load/client:idle/client:visibleでは、インタラクティブ性はHTMLの上に追加され、HTMLの下には隠れません。これらのディレクティブは、クロール可能な基盤からコンテンツを取り除かずに1つのコンポーネントへJSを追加します。client:onlyはこのパターンを壊します。サーバーレンダリングを完全に省略するため、計画しない限り静的HTMLに本当の空白ができます。Islandのハイドレーションは選択的で、レジューム可能性ではありません。2つを混同しないでください。
4. 静的シェルがクローラーの見るもの。 Server Islandsでは、クローラーが読むのは遅延コンテンツではなく静的シェル内のフォールバックです。判断ルールは、インデックス登録対象コンテンツをメインテンプレートに置き、個人化/動的コンテンツをIslandに置くことです。
5. ブラウザーの拡張 ≠ 構造の変更。
View Transitionsはhistory.pushStateによるソフトナビゲーションでブラウザー体験を変えますが、各URLが完全なHTMLページであるというクロール体験は変えません。基礎にあるMPAを維持する拡張はSEOに安全です。
6. ビルド時に検証する。 Content Collections + Zodは、「titleを追加するのを覚えておく」を「titleがなければビルドを公開できない」に変えます。SEO要件を型システムへ押し込み、忘れられる作業ではなくします。
Astro SEO — チートシート
自動で行われることと、自分で行うこと
| 項目 | Astroが行うか | 自分が行うこと |
|---|---|---|
| 静的HTML出力 | ✅ デフォルト(staticモード) | 何もしない — ただしデフォルトであり、ルートごとのprerenderを確認 |
| ハイドレーションされないコンポーネントはコンポーネントJSなしで配信 | ✅ Islands(client:onlyを除く) | 必要な場所だけclient:*を使い、インデックス登録対象をclient:onlyの外に置く |
| 画像WebP + 寸法 + 遅延読み込み | ✅ <Image> | LCP画像をeagerに上書き |
altの強制 | ✅ 欠落時はコンパイルエラー | よいaltテキストを書く |
| サイトマップ | ⚠️ プラグイン、静的ルートのみ | astro add sitemap + site:設定 + ランタイム専用URLはcustomPages |
| robots.txt内のサイトマップ | ❌ | 行を手動で追加 |
| Metaタグ/canonical | ❌ | BaseLayout.astro props |
| 構造化データ(JSON-LD) | ❌ | <head>へ追加 |
| robots.txt | ❌ | public/にファイルを置く |
| 成果の保証(クロール可能性/順位/CWV) | ❌ — 仕組みだけ | デプロイ済みルートを自分で検証する |
出力モード
| モード | 設定 | SEO(検証後) | 用途 |
|---|---|---|---|
| static(デフォルト) | — | ✅ 最初のリクエストで完全なHTML | ほとんどのコンテンツ。CDNエッジから配信 |
| server | output: 'server' | ✅ クローラーにはstaticと同等 | 認証、リアルタイム、個人化 |
| ルートごとの上書き | staticデフォルトではexport const prerender = false、serverデフォルトでは= true | ✅ | プリレンダリングとオンデマンドのルートを混在 |
Islandディレクティブ
client:load— すぐハイドレーションする。client:idle— ブラウザーがアイドルになったときハイドレーションする。client:visible— スクロールして見えるときハイドレーションする(ファーストビューより下に最適で、LCPを保護する)。client:only— サーバーレンダリングを完全に省略する。 ブラウザーがハイドレーションするまでこのコンポーネントのHTMLはなく、他のディレクティブのように追加的ではありません。
速いルール
site:がない → サイトマップなし(静かに失敗)。- Server Islandのインデックス登録対象コンテンツ → クローラーはフォールバックを見る。Server Islandsにはアダプターが必要。
client:onlyの中だけにあるインデックス登録対象コンテンツ → 完全にHTMLなし。- サイトマップは静的ルートを対象にする →
customPagesでランタイム専用URLを追加。 - View Transitionsは
history.pushStateを使う → SEOに安全。下にあるのはMPA。 - static/server出力とIslandは仕組みであって保証ではない。成果を主張する前に、デプロイ済みルート、ステータスコード、完全なHTMLを検証する。
- 速くても空のページは順位が上がらない。速度は1つのシグナルであり、唯一のシグナルではない。
Astroのビルド済みHTMLを監査する
これはastro buildの後に実行します。ソースのコンポーネントツリーではなく、クローラーが受け取る成果物を確認します。
find dist -name '*.html' -type f | while IFS= read -r file; do
canonicals=$(grep -Eio '<link[^>]+rel=["'"']canonical["'"'][^>]*>' "$file" | wc -l | tr -d ' ')
titles=$(grep -Eio '<title>[^<]*</title>' "$file" | wc -l | tr -d ' ')
if [ "$canonicals" -ne 1 ] || [ "$titles" -ne 1 ]; then
printf '%s\ttitles=%s\tcanonicals=%s\n' "$file" "$titles" "$canonicals"
fi
done空の結果は、生成されたすべてのHTMLファイルにtitleとcanonicalがちょうど1つずつあることを意味します。値が正しいかどうかは検証しないため、別途サンプル確認してください。これはビルド成果物だけを確認し、オンデマンド(output: 'server')のルートやServer Islandsについては何も言いません。それらは静的ファイルとして存在しないためです。
本番のライブURLをサンプル確認する
オンデマンドでレンダリングされるもの(output: 'server'のルート、ルートごとのprerender = false、Server Islands)には、上のビルド出力チェックは適用されません。代わりに実際のデプロイ済みレスポンスを確認します。
# Replace with your real URLs
for url in "https://example.com/" "https://example.com/some-server-route/"; do
echo "== $url =="
curl -sS -D - -o /dev/null "$url" | grep -Ei '^(HTTP|location|cache-control):'
done想定するステータスコードを確認します(ライブページは200、リダイレクトする場合は実際のリダイレクトコード。確認せず302と301を決めつけない)。Server Islandを含むページを確認する場合は、curl -sS "$url"がフォールバックシェルではなく完全なマークアップを返すことも確認します。これはastro devではなく本番に対して行ってください。アダプターとランタイムの挙動はローカルと異なることがあります。
Astroサイト向けのツール
@astrojs/sitemap— 公式のサイトマップインテグレーション(astro add sitemap)。設定のsite:を忘れないでください。astro-seo(npm) — title、description、Open Graph、Twitterカード、canonicalを1つのタグにまとめる任意のコミュニティコンポーネント。astro-seo-schema(npm) — Astro向けの型付きJSON-LD構造化データヘルパー。- astro:assetsの
<Image>/<Picture>— 組み込みの画像最適化(WebP/AVIF、寸法、遅延読み込み、altの強制)。 - URL検査(Google Search Console) — コンテンツがクロール済みHTMLにあることを確認します(AstroならすでにView Sourceにあるはずです。簡単な健全性チェックです)。
- JSレンダリングクローラー — Ahrefs Site AuditやScreaming Frogでサイト全体の生DOMとレンダリングDOMの一致を確認します(プリレンダリングされたルートでは一致するはずですが、決めつけず確認し、オンデマンドやServer Islandのルートは別に確認します)。
- IndexNow — デプロイ/公開手順と組み合わせて、BingとYandexへ静的ページをすぐ知らせます。
確認テスト:Astro SEO
AstroのアーキテクチャがSEOにどう影響するかを問う5つの短い質問です。それぞれ回答を選んでから、確認してください。
時間をかける価値のあるリソース
関連する私の執筆
- JavaScript SEO: A Definitive Guide — AstroのHTML優先出力が大きな利点になる理由の背景にある、レンダリングの基礎。
- The Beginner’s Guide to Technical SEO — フレームワークの選択が大きな全体像のどこに位置するか。
私の講演
- How Search Works(SlideShare)— クロール、レンダリング、インデックス登録、順位付けについての解説です。AstroのSSGデフォルトが短絡させるパイプラインでもあります。(恒常的な免責:「This is my understanding of systems… not going to be 100% complete or accurate.」)
業界の資料
- Astro Docs: Islands Architecture — Astroがクライアント側JSを取り除く方法の正式な説明。
- Astro Docs: @astrojs/sitemap — 公式設定、
site:要件、filter/serialize/i18nオプション。 - Astro Docs: Server Islands —
server:defer、フォールバックコンテンツ、クローラーが見ないクライアント取得の挙動。 - Joost de Valk: Astro SEO Complete Guide — Yoast創業者による最も権威ある実務家ガイド。現代のAI対応パターンとIndexNowに強い内容です。
- Google Search Central: Understand JavaScript SEO Basics — レンダリングキュー、クロール可能なリンク、AstroのView Transitionsが従うHistory APIの指針。
- Astro: 2023 Web Framework Performance Report — Astroと他のフレームワークを比較するCore Web Vitalsデータ。
- Core Web Vitals、WordPress、Astro — AstroとWordPressのパフォーマンス比較に関する独立した報道。
引用する価値のある統計
以下の数字はすべてAstroの2023年Web Framework Performance Reportと、そこからのSEJの報道に基づきます。現在の数字ではなく、2023年時点のベンチマークとして扱ってください。
- Astroサイトの50%超がGoogleのCore Web Vitals Assessmentに合格 — 約40,5%の業界平均を上回り、AstroとSvelteKitだけが当時の主要フレームワークでこのベースラインを超えました(Next.jsは約25%、Nuxtは約20%)。 出典
- AstroのINP合格率は68,8% — JS駆動のナビゲーションがないMPAアーキテクチャによるもので、メインスレッドを空けておきます。 出典
- ページ重量の中央値は1,65 MB — データセットで最も軽い値です。 出典
- LCP:Astro約0,44秒、WordPress約0,81秒 — レポートの比較では約46%高速です。 報道
変更履歴
2026年8月8日に更新。
編集概要と記録された変更の詳細。変更の詳細
-
変更の詳細な注記は現在英語でのみ提供されています。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。
2026年7月17日に更新。
編集概要と記録された変更の詳細。変更の詳細
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。