VueのSEO
素の Vite + Vue 3 スキャフォールドではコンテンツが生の HTML に入らない CSR が標準です。Vue アプリをクロール、インデックス可能にするためのルーターモード、@unhead/vue、vite-ssg のプリレンダリング、Nuxt の SSR/SSG、ハイドレーション、Core Web Vitals を解説します。
言語
素の Vite + Vue 3 アプリは標準では CSR で、空に近い HTML シェルを配信し、ブラウザでページを構築します。Google はレンダリングできますが遅延があり、非同期データを見落とす可能性があります。Bing やソーシャルスクレイパーは JavaScript を実行できないことも少なくありません。Vue Router の history モードを使い、@unhead/vue で <head> を管理し、vite-ssg のプリレンダリング、SSR、または Nuxt の SSG でコンテンツを HTML に含めます。動的レンダリングは非推奨です。
TL;DR — Vueはデフォルトでブラウザ内でページを構築します。つまり、検索エンジンが最初にダウンロードする生のHTMLはほぼ空で、実際のコンテンツはJavaScriptが実行された後にのみ表示されます。Googleは通常これを処理できますが、Bingやソーシャルシェアプレビューを作成するボットはしばしば処理できません。修正方法:Vue Routerの「history」モードを使用してクリーンなURLにし、
@unhead/vueという小さなライブラリをタイトルと説明に追加し、ランキングが必要なページでは、ブラウザ内だけでなく事前にHTMLを構築します(プリレンダリングまたはNuxt)。
Vueに特別なSEO対策が必要な理由
通常の方法(Vite + Vue)でVue 3サイトを構築すると、サーバーは小さなHTMLファイル(基本的には空のコンテナ)と大きなJavaScriptバンドルを送信します。ブラウザはそのJavaScriptを実行して実際のページを描画します。これは**クライアントサイドレンダリング(CSR)**と呼ばれます。 Evidence for this claim A Vue application can render its interface in the browser with client-side JavaScript. Scope: Vue client-side rendering architecture. Confidence: high · Verified: Vue: SSR guide
人間は決して気づきません。検索エンジンは気づくかもしれません。クローラーが最初にダウンロードするのは、そのほぼ空のコンテナです。何かを見るためにはJavaScriptを実行する必要がありますが、すべてのクローラーがそれをうまく実行するわけではありません。
- Googleは最新版のChromeを実行し、Vueアプリをレンダリングできます。ただし、レンダリングは後でキューで行われ、コンテンツが遅いデータリクエストを待つ場合、Googleは読み込みが完了する前に移動してしまう可能性があります。
- Bing、DuckDuckGo、ソーシャルプレビューボット(X、Slack、iMessageにリンクを貼り付けたときに小さなカードを作成するもの)は、JavaScriptの実行がはるかに信頼性に欠けます。通常のVueアプリでは、ソーシャルプレビューが空白になることがあります。
正しく行うべき3つのこと
-
Vue Routerで「hash」モードではなく「history」モードを使用します。 ハッシュモードのURLは
example.com/#/aboutのようになります。Vue Routerの公式ドキュメントによると、ハッシュモードは「SEOに悪影響を与える」とされています。createWebHistory()を使用して、URLがexample.com/aboutのようになるようにします。 Evidence for this claim Vue Router recommends HTML5 history mode for normal-looking URLs and warns that hash mode has a negative SEO effect. Scope: Vue Router history modes. Confidence: high · Verified: Vue Router: History modes -
@unhead/vueでタイトルとメタタグを管理します。 デフォルトでは、すべてのVueページが同じタイトルと説明を共有します。@unhead/vueを使用すると、各ページが独自のタイトルと説明を設定できます。ソーシャルプレビューを駆動するOpen GraphタグとTwitterタグも含まれます。 -
ランキングが必要なページでは、コンテンツをHTMLに配置します。 すべてをブラウザで構築する代わりに、事前に構築して、クローラーが到着したときにコンテンツがすでに存在するようにします。簡単な入り口は、
vite-ssgというツールを使ったプリレンダリングです。より大規模または動的なサイトには、Nuxt(これに関する公式のVueフレームワーク)がそれを自動的に行います。
単にNuxtを使うべきですか?
SEOが実際に重要であるほとんどのサイトでは、はい—Vue自身のドキュメントもそれを推奨しています。Nuxtはレンダリング、メタタグ、サイトマップ、robots.txtを自動的に処理します。サイトがかなり静的(マーケティングサイト、ドキュメント、ブログ)である場合、vite-ssgはフレームワークを切り替える必要のない軽量なオプションです。
より深いバージョン(Googleのレンダリングキューの仕組み、@unhead/vueのコード、プリレンダリングとSSR、ハイドレーションの不一致、Core Web Vitals)が必要ですか?Advancedタブに切り替えてください。
TL;DR — 素の Vite + Vue 3 はデフォルトで CSR のため、コンテンツは生の HTML に含まれません。Google は最新の Chromium WRS で後からレンダリングしますが、処理はキューに入り、
onMountedで取得する非同期データは見落とされる可能性があります。Bing やソーシャルスクレイパーは JavaScript を実行しないことも少なくありません。必須事項は、Vue Router のcreateWebHistory()(ハッシュモードは「SEO に悪影響」)、<head>を管理する@unhead/vue/useSeoMeta()、そしてコンテンツを HTML に入れるレンダリング戦略です。内容が安定したサイトにはvite-ssgによるプリレンダリング、完全な SSR/SSG には Nuxt を使います。動的レンダリングは 非推奨で、prerender-spa-pluginはレガシーです。ハイドレーションの不一致と CSR バンドルによる LCP 悪化にも注意してください。一般的な仕組みは JavaScript SEO で解説しています。
デフォルトのVite + Vueスキャフォールドはクライアントサイドレンダリングされる
素の npm create vue@latest アプリ(Vite + Vue)は、ほぼ空の HTML シェルと JavaScript バンドルを出荷します。ブラウザはそのバンドルを実行して DOM を構築します。これはユーザーにとっては問題ありませんが、クローラーにとっては問題です。生の HTML にはほとんどコンテンツが含まれておらず、すべてがレンダリングに依存しています。
これはデフォルトのスキャフォールドの特性であり、Vue 自体の限界ではありません。Vue コアはサーバーレンダリング(createSSRApp)と静的生成を第一級のパスとしてサポートしており、Vue 自身の SSR ガイドは、ほとんどの本番 SSR/SSG 作業を手作りのセットアップではなく Nuxt に誘導しています。したがって、修正に手を伸ばす前に、アプリが実際に何を出荷しているかを確認してください。レンダリング設定のない素の Vite SPA は CSR です。Nuxt や vite-ssg の背後にある同じアプリは CSR ではありません。
Vue 自身の SSR ガイドは、これをしないことの利点について率直です。サーバーサイドレンダリングでは、「検索エンジンのクローラーは、完全にレンダリングされたページを直接見ることができます。」 その反面、デフォルトで出荷されるのは、JavaScript が実行された後にのみ存在するコンテンツです。 Evidence for this claim Vue server-side rendering sends rendered HTML so crawlers can directly see page content. Scope: Vue SSR benefits; does not guarantee indexing. Confidence: high · Verified: Vue: SSR guide
(Vue 2 は 2023 年 12 月にサポート終了となりました。ここではすべて Vue 3 です。)
Googlebot が Vue アプリを処理する方法
Google は JavaScript を段階的に処理します。生の HTML をクロールし、次に最新のヘッドレス Chromium インスタンス(Web Rendering Service)でレンダリングし、レンダリングされた結果をインデックスに登録します。これから2つのことが導かれます。
- レンダリングはキューに入れられ、遅延します。 ページはレンダリングキューに置かれます。通常は数秒から数分ですが、急増することもあります。JS の実行後にのみ存在するコンテンツはすぐにはインデックス可能ではありません。生の HTML にあるコンテンツはインデックス可能です。
- 非同期データが本当のリスクです。 同期 JavaScript は確実にレンダリングされます。マウント後に API から取得されたデータは、確実に取得されるとは限りません。Vue の SSR ガイドは明確に述べています:「アプリがローディングスピナーで始まり、Ajax でコンテンツを取得する場合、クローラーはあなたが終了するのを待ちません。つまり、SEO が重要なページで非同期に取得されたコンテンツがある場合、SSR が必要になる可能性があります。」 実際には:
onMountedで取得されたデータはクライアントのみであり、レンダリングしないクローラーには見えません。レンダリングするクローラーでもリスクがあります。
John Mueller は、静的 HTML がほぼ同一で、すべての固有コンテンツが JavaScript に依存する SPA スタイルのセットアップの失敗モードについて説明しています。その JS を適切に実行できない場合、ページは Google にとって同じように見え、焦点は JS で読み込まれたコンテンツではなくボイラープレート HTML に留まります。教訓は、より広範な JavaScript SEO ページと同じです。コンテンツを迅速かつ確実に DOM に取り込むことです。
Bing とソーシャルボットは Google よりもこれが苦手です。 Bing には Google に匹敵するレンダリングパイプラインがなく、ソーシャルプレビュースクローラー(X、Slack、iMessage)は一般的に JavaScript をまったく実行しません。そのため、素の CSR Vue アプリは空の共有プレビューを生成します。Bing のトラフィックやソーシャル共有が重要な場合は、プリレンダリングや SSR は必須です。
Vue Router:ハッシュモードではなく createWebHistory() を使用する
Vue Router には2つの履歴モードがあります。ハッシュモード(createWebHashHistory())は example.com/#/about のような URL を生成します。Vue Router のドキュメントは、# 以降はサーバーが無視するフラグメントであるため、「SEO に悪影響を与える」 と述べています。 Evidence for this claim Vue Router hash history uses a URL fragment that is not sent to the server and is discouraged for SEO. Scope: Vue Router hash history. Confidence: high · Verified: Vue Router: History modes
HTML5 履歴モードを使用してください:
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [/* ... */],
})履歴モードはクリーンな URL(example.com/about)を提供しますが、サーバーフォールバックが必要です。ルートへの直接リクエストは、Vue が引き継げるように index.html を提供する必要があります。そうしないと、直接アクセスは 404 になります。ホストでそのキャッチオールを設定してください(Nginx の try_files、Netlify/Vercel/Cloudflare での SPA リライトなど)。
そのリライトの範囲を慎重に設定してください。広すぎるキャッチオールは、存在しない静的アセット、実際の API ルート、または実際に 404 にしたいページに対しても index.html を提供します。これにより、以下のソフト 404 ガイダンスが静かに無効になり、壊れたリンクが「機能した」ように見えるページの背後に隠れる可能性があります。
真の404状態に対しては、ソフト404を避けてください。クライアントサイドの「見つかりません」ビューが200を返すと、空のシェルとしてインデックスされる可能性があります。Googleのガイダンスは、実際の404ステータスを返すURLにリダイレクトするか、エラーページに<meta name="robots" content="noindex">を追加し、ビュー間のルーティングにはHistory APIを使用することです。
headとmetaの管理: @unhead/vue
デフォルトでは、すべてのVueルートが1つの<title>と1つのmeta descriptionを共有します。ここでタグの歴史が重要になるのは、古い回答が行き止まりだからです:
vue-meta— Nuxt 2時代のライブラリ。レガシー。@vueuse/head— その後継だが、現在はサンセット。@unhead/vue— 現在のコミュニティ標準であり、非NuxtのVue 3アプリで使用すべきものです。
扱いやすい入口は useSeoMeta() コンポーザブルです。型安全かつ XSS に配慮され、Open Graph や Twitter Card を含む 100+ の meta タグに対応しています:
import { useSeoMeta } from '@unhead/vue'
useSeoMeta({
title: 'Vue SEO Guide',
description: 'How to make a Vue 3 app crawlable and indexable.',
ogTitle: 'Vue SEO Guide',
ogDescription: 'How to make a Vue 3 app crawlable and indexable.',
twitterCard: 'summary_large_image',
})Metaはリアクティブにできます。getterやcomputed値を渡すと、データが変わったときにタグが更新されます。canonicalタグについては、最も安全なパターンは依然としてHTMLであり、JSではありません: Googleのガイダンスは*“the best way to set the canonical URL is to use HTML,“*であり、JavaScriptで注入する必要がある場合は、常にHTMLが設定するのと同じ値に設定してください。(私はAhrefsでJS canonicalをテストし、Googleがそれらを尊重することを発見しました。Googleがドキュメントに例外を追加するきっかけにもなりましたが、HTMLの方が依然としてリスクが低い道です。)
レンダリング戦略を選ぶ
これが実際に効果を発揮する決断です。フレームワークに依存しないJavaScript SEOページと同じメニューを、Vueに適用したものです。
クライアントサイドレンダリング(CSR)— デフォルトであり、リスクが高いもの。 ログインの背後にあるアプリ的なページ、ダッシュボード、インデックスされる必要がないものには許容されます。ランク付けされるか共有される必要があるコンテンツには許容されません。
vite-ssg によるプリレンダリング。 コンテンツが安定した Vue 3 SPA では、vite-ssg がビルド時に静的 HTML を生成します。ビルドスクリプトを vite build から vite-ssg build に切り替えるだけで、@unhead/vue も組み込まれています。マーケティングサイト、ドキュメント、ブログに適していますが、リクエストごとに大きく変わるページで SSR の代わりにはなりません。webpack 時代の古い prerender-spa-plugin はレガシーで、実質的に保守されていません。現在は vite-ssg または Nuxt を選びます。
サーバーサイドレンダリング。 Vue の公式ガイドは @vue/server-renderer を使う手動 SSR も説明していますが、多くのプロジェクトには自作よりメタフレームワークを明示的に勧めています。単純なケースについては “if you’re only investigating SSR to improve the SEO of a handful of marketing pages … then you probably want SSG instead of SSR.” (翻訳) 「少数のマーケティングページの SEO 改善だけを目的に SSR を検討しているなら、おそらく SSR ではなく SSG が適しています」と述べています。手動 SSR では、アプリ、ルーター、ストアをリクエストごとに新しく作成してください。長時間動作する Node サーバーではモジュール単位のシングルトンが再利用され、ある利用者のデータで変更した共有状態が別のレスポンスへ漏れる可能性があります。Nuxt が多くのプロジェクトに推奨される理由の一つは、この分離を処理するためです。
Nuxt — 推奨される完全なソリューション。 NuxtはSSRとSSGをすぐに使える状態で提供し、組み込みのuseSeoMeta()とhead管理、そしてsitemap、robots.txt、構造化データのための@nuxtjs/seoモジュールを備えています。SEOが重要なほとんどのVueプロジェクトでは、これがVue自身のドキュメントが指す道です。(Nuxtには独自の深さがあります — 別途カバーされています。これはクロスリンクであり、深掘りではないとお考えください。)
動的レンダリング — しないでください。 ボットにプリレンダリングされたHTMLを、ユーザーにSPAを提供することは常に回避策であり、Googleは2024年にこれを非推奨とし、実装ドキュメントを削除しました。代わりにSSRまたはSSGで構築してください。
ドキュメントに特化して言えば、VitePressはVueネイティブの静的サイトジェネレーターです。すべてのページがプレーンなHTMLとして配信されるため、JSレンダリングの障壁がなく、SEOはfrontmatter(title、description、head)またはcanonical/動的タグ用のtransformHeadビルドフックで設定されます。
ハイドレーションの不一致は、パフォーマンスの問題だけでなくSEOの問題でもある
SSR/SSG を行う場合、クライアントは createSSRApp()(通常の createApp() ではありません)でマウントし、サーバーが生成した HTML をゼロから作り直すのではなくハイドレーションします。サーバーの HTML とクライアント側のレンダリングが一致しないと、Vue は不一致のノードを破棄して再レンダリングします。SEO の観点では、Google がサーバーレンダリング版からインデックスした内容と、ハイドレーション後にユーザーが見る内容が異なる可能性があります。これは単なるちらつきではなく、品質シグナルの不一致です。よくある原因は、無効な HTML の入れ子、テンプレート内のランダム値、サーバーとクライアントで異なる日時です。Vue 3.5+ では、意図的な差異について不一致の警告を選択的に抑える data-allow-mismatch が追加されました。ただし、これはコンソールを静かにするだけで、サーバーとクライアントの出力を同等にするものではありません。診断していない不一致を隠すためだけには使わないでください。
Core Web VitalsはVue固有の関心事です
デフォルトのCSR Vueは、最大のコンテンツが描画される前にダウンロード、解析、実行する必要がある大きなJSバンドルを配信するため、何もしなければLCPが低下します。対策は以下の通りです。
- コード分割(Vite のデフォルト)と遅延読み込みルートを使い、アプリ全体を最初から配信しないようにします。
fetchpriority="high"を LCP のヒーロー画像に設定します。- Vapor Mode は、対象コンポーネントで仮想 DOM を迂回するオプトインのコンパイラモードで、SSR ページのハイドレーションコストを削減できる可能性があります。対象は Vue 3,6 で、3,5 ではありません。2026 年半ば時点ではまだ実験段階(ベータ/リリース候補)で、安定版の 3,5.x 系には含まれていません。注視する価値はありますが、現時点の本番環境で依存すべき機能ではありません。
Vueでの構造化データ
Google は構造化データを読み取る前に JavaScript を実行するため、JSON-LD の注入は機能します。信頼できるパターンは、@unhead/vue の useHead() で script を設定し、その type を application/ld+json にすることです。レンダリングに依存するため、Google が認識したと決めつけず、URL Inspection で確認してください。
位置づけ
Vue SEOは、一般的なJavaScript SEO問題(パリティ、インタラクション、状態、タイミング)の一例であり、ヘッドレスCMSの状況とほぼすべてを共有しています。そこでは、フロントエンドのレンダリングモードが結果を決定します。
上記のすべてのオプションに当てはまる注意点が1つあります。SSRとSSGはコンテンツをHTMLに取り込みますが、どちらもインデックス、ランキング、Core Web Vitals、またはハイドレーションがサーバー出力と完全に一致することを保証しません。これらはJavaScriptレンダリングの障壁を取り除くだけで、残りのSEO(および正確性)は依然としてあなた次第です。
1つだけ覚えておくなら:コンテンツをHTMLに取り込むこと。 それ以外はすべて詳細です。
AIまとめ
Advancedバージョンの簡潔な見解:
- デフォルトの Vite + Vue スキャフォールドは CSR — 素の
npm create vue@latestアプリはほぼ空の HTML シェルを配信し、ブラウザで DOM を構築します。これは素のスキャフォールドの特性であり、Vue 自体の限界ではありません。Vue コアは SSR(createSSRApp)と SSG も第一級の経路としてサポートしています。 - Google は Vue をレンダリングできますが、注意点があります — 常時更新される Chromium ベースの WRS が JavaScript を実行する一方、レンダリングはキューに入り遅延し、非同期データ(たとえば
onMountedで取得するデータ)は見落とされる可能性があります。Vue の SSR ドキュメントによれば、クローラーはスピナーの後ろで行われる Ajax 取得の完了を「待ってくれません」。 - Bing とソーシャルスクレイパーはさらに不利です — JavaScript をまったく実行しないことが多いため、素の CSR Vue アプリでは共有プレビューが空になります。
- ルーター: ハッシュモードではなく
createWebHistory()を使います(ハッシュは「SEO に悪影響」があります)。history モードにはサーバー側のindex.htmlフォールバックが必要ですが、実在する静的アセット、API ルート、意図したエラー応答まで飲み込まないよう範囲を限定し、ソフトエラーを避けます。 - head/メタ情報: 現在の標準は
@unhead/vueとuseSeoMeta()です。vue-metaはレガシーで、@vueuse/headは終了しています。canonical は HTML で出力するのが望ましいです。 - レンダリング戦略が決定的です: CSR(リスクはあるがアプリ画面には可)→
vite-ssgによるプリレンダリング(内容が安定したサイト)→ Nuxt による SSR/SSG(推奨される包括的な解決策)。prerender-spa-pluginはレガシーで、動的レンダリングは非推奨です。SSR を手作業で構築する場合は、リクエスト間の状態漏れを防ぐため、リクエストごとにアプリ、ルーター、ストアを新しく作成します。 - VitePress はドキュメントサイト向けです(通常の静的 HTML)。
- ハイドレーションには
createSSRApp()を使います。不一致はサーバーとクライアントのコンテンツ差分を生み、単なるちらつきではなく SEO の品質問題になります。Vue 3.5+ のdata-allow-mismatchは意図した差異の警告を抑えるだけで、2 つのレンダリングを同等にはしません。 - Core Web Vitals: 大きな CSR バンドルは LCP を悪化させます。コード分割、遅延ルート、
fetchpriority="high"、そして実験段階の Vapor Mode(Vue 3.6 ベータ/RC、まだ安定版ではありません)を検討します。 - 構造化データは
@unhead/vueのuseHead()で JSON-LD として設定し、URL Inspection で確認します。 - ここで挙げた方法はいずれも、インデックス、ランキング、CWV、ハイドレーションの一致を保証しません — SSR/SSG は JavaScript レンダリングの障壁を取り除くだけで、残りの SEO は引き続き実装側の責任です。
公式ドキュメント
Vueと検索エンジンからの一次情報ドキュメント。
Vue
- Server-Side Rendering (SSR) | Vue.js — SSRのSEO上の利点、非同期/スピナーの注意点、およびマーケティングページ向けSSGの推奨。
- Different History modes | Vue Router —
createWebHistory()とハッシュモードの比較、SEOに関する注意、およびサーバーフォールバックの要件。 - useSeoMeta() · Unhead — 型安全なメタ管理のための現在の
@unhead/vueコンポーザブル。 - Site Config | VitePress と Frontmatter Config | VitePress — Vueベースのドキュメントサイト向けSEO設定。
- antfu-collective/vite-ssg | GitHub — Vue 3 SPA向けのビルド時プリレンダリング。
- JavaScript SEO の基本を理解する — 2 段階の処理、History API の推奨、ソフト 404 の処理、HTML canonical。
- 回避策としての動的レンダリング — 現在は非推奨と明記されており、代わりに SSR、静的レンダリング、ハイドレーションが推奨されています。
- JavaScript SEO の新しい動画シリーズを紹介 — Google 公式の JavaScript SEO シリーズ(Vue.js の回を含む)。
ソースからの引用
VueとGoogleからの公式声明。各リンクは、ソースページの引用箇所にジャンプするディープリンクです。
Vue — SSR & SEO
- “Better SEO: the search engine crawlers will directly see the fully rendered page.” (翻訳) 「SEOの向上:検索エンジンのクローラーが完全にレンダリングされたページを直接見ることができます。」 — Vue.js SSRガイド。 引用へジャンプ
- “As of now, Google and Bing can index synchronous JavaScript applications just fine. Synchronous being the key word there. If your app starts with a loading spinner, then fetches content via Ajax, the crawler will not wait for you to finish.” (翻訳) 「現時点では、GoogleとBingは同期型JavaScriptアプリケーションを問題なくインデックスできます。ここでのキーワードは「同期」です。アプリがローディングスピナーで始まり、Ajaxでコンテンツを取得する場合、クローラーは完了するまで待ってくれません。」 引用へジャンプ
- “If you’re only investigating SSR to improve the SEO of a handful of marketing pages … then you probably want SSG instead of SSR.” (翻訳) 「少数のマーケティングページのSEOを改善するためだけにSSRを検討しているのであれば…おそらくSSRではなくSSGが必要でしょう。」 引用へジャンプ
Vue Router — ヒストリーモード
- ハッシュモードについて:“It does however have a bad impact in SEO.” (翻訳) 「ただし、SEOに悪影響を及ぼします。」 引用へジャンプ
Google — JavaScript SEOの基本
- 正規URLについて:“The best way to set the canonical URL is to use HTML, but if you have to use JavaScript, make sure that you always set the canonical URL to the same value as the original HTML.” (翻訳) 「正規URLを設定する最良の方法はHTMLを使用することですが、JavaScriptを使用する必要がある場合は、常に正規URLを元のHTMLと同じ値に設定してください。」 引用へジャンプ
Google — 動的レンダリング(非推奨)
- “Dynamic rendering was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines.” (翻訳) 「動的レンダリングは回避策であり、検索エンジンにおけるJavaScript生成コンテンツの問題に対する長期的な解決策ではありませんでした。」 引用へジャンプ
Vue SEOチェックリスト
Vue 3アプリがクロール可能かつインデックス可能であることを確認するためのチェック項目:
- Vue Router が
createWebHistory()(HTML5 history モード)を使い、createWebHashHistory()を使っていない。 - サーバーに
index.htmlフォールバックがあり、ルートへの直接アクセスが 404 にならない。 -
@unhead/vueが組み込まれ、すべてのページが共通のデフォルトではなく、固有のタイトル、説明、canonical を設定している。 - Open Graph/Twitter Card タグがあり、ソーシャルスクレイパーに実際にレンダリングされる(CSR だけでなく、配信される HTML に含まれる)。
- canonical は可能な限り HTML で設定し、JavaScript で注入する場合も同じ値になっている。
- SEO に重要なコンテンツが HTML に含まれている(SSR/SSG/プリレンダリング)。CSR ページの
onMountedで取得していない。 - クライアント側の not-found 状態が実際の
404またはnoindexを返し、ソフト 404 のシェルになっていない。 - JavaScript と CSS がブロックされていないことを
robots.txtで確認した。 - 新しいビルドが 動的レンダリングに依存していない(Google により非推奨)。
- Core Web Vitals に合格している — コード分割、遅延ルート、LCP 画像の
fetchpriority="high"。 - SSR/SSG の場合、ハイドレーションの不一致がない(コンソールを確認し、
data-allow-mismatchは意図した差異にだけ使う)。 - 構造化データ(JSON-LD)が、URL Inspection でレンダリング後の HTML に含まれることを確認した。
メンタルモデル
1. デフォルトが落とし穴です。 Vue 3は初期状態ではCSRです — コンテンツは生のHTMLに含まれていません。Vue SEOのすべては、見つけられる必要があるページに対してそのデフォルトを上書きすることです。
2. レンダリングが結果を左右する。
最も効果の高い選択は、HTMLがどのように生成されるかです。CSR(リスクあり)→
プリレンダリング/vite-ssg(コンテンツ安定)→ NuxtによるSSR/SSG(動的、SEOに重要)。
コンテンツをHTMLに含める最も軽量なオプションを選びましょう。
3. マウント後の非同期ではなく、HTML内で同期する。 同期的に存在するコンテンツは確実にレンダリングされます。マウント後に取得したデータは、レンダリングが遅いクローラーには見逃され、レンダリングしないクローラーには完全に無視される可能性があります。
4. 2種類のボット。 Googleはレンダリングします(最終的には)。Bingやソーシャルスクレイパーはほとんどレンダリングしません。Bingのトラフィックやシェアプレビューが重要な場合は、より劣った方に合わせて設計してください。つまり、CSRではなくHTMLです。
5. 新しいVueプロジェクトのための決定木。
ログインの背後にある純粋なアプリ?CSRで問題ありません。コンテンツが安定したマーケティング/ドキュメント/ブログ?vite-ssgまたはVitePress。動的でリクエストごとに変わるSEOに重要なコンテンツ?Nuxt。動的レンダリングやprerender-spa-pluginには決して手を出さないでください。どちらも2026年には行き止まりです。
6. サーバーとクライアントは一致していなければならない。 ハイドレーションの不一致は単なるパフォーマンス上の些細な問題ではありません。Googleがインデックスしたものとユーザーが受け取るものとの間のコンテンツの差異です。2つのレンダリングを同一に保ってください。
Vue SEO — チートシート
ルーターモード
| モード | URL | SEO |
|---|---|---|
createWebHistory() | example.com/about | これを使用(サーバーフォールバックが必要) |
createWebHashHistory() | example.com/#/about | ”Bad impact in SEO” — 避ける |
Head / メタライブラリ
| ライブラリ | ステータス |
|---|---|
vue-meta | レガシー(Nuxt 2時代) |
@vueuse/head | サンセット |
@unhead/vue (useSeoMeta()) | 現在の標準 |
レンダリング戦略
| 戦略 | いつ | SEOリスク |
|---|---|---|
| CSR(デフォルト) | アプリページ、ログインの背後 | 最高 |
vite-ssg プリレンダリング | コンテンツが安定したSPA(マーケティング/ドキュメント/ブログ) | 低 |
| SSR(Nuxt) | 動的でリクエストごとのページ | 低 |
| SSG(Nuxt / VitePress) | ビルド時に既知のコンテンツ | 最低 |
prerender-spa-plugin | — | レガシー/メンテナンスされていない — 使用しない |
| 動的レンダリング | — | Googleによって非推奨 — 使用しない |
早わかり
- GoogleはVueをレンダリングします(常緑のChromium WRS)— ただし遅延し、非同期データは見逃される可能性があります。
- Bing + ソーシャルスクレイパーはしばしばJSを実行しません — 素のCSR = 空のシェアプレビュー。
- 正規化:HTML優先。JSの正規化も機能しますが、リスクが高くなります。
- Vue 2はEOL(2023年12月)— Vue 3のみ。
Vueルートはどのようにレンダリングすべきか?
Choose a Vue SEO rendering path
Vue SEOの間違い
- 検索ランディングページをVite SPAシェルとして配信する。 重要なコンテンツがソースHTMLに含まれるように、Nuxt SSR/SSGまたはプリレンダリングを使用します。
- 公開コンテンツルートにハッシュモードを使用する。 フラグメントは通常のサーバーURLを作成しません。ホストフォールバックを正しく設定したヒストリールーティングを使用します。
- クライアントフェッチ後にのみheadタグを設定する。 head統合を通じて、サーバー/ビルドデータからメタデータを生成します。
- 長期的な修正として動的レンダリングを使用する。 ボット固有の出力ではなく、一貫したユーザー/クローラーレンダリングパスを維持します。
- Googleでのみテストする。 生のHTMLは、アプリケーションを完全に実行しない他の検索エンジン、ソーシャルスクレイパー、ツールにとって重要です。
生のHTMLにはVueマウント要素のみが含まれている
考えられる原因: ルートがCSRのみである。修正: Nuxt SSR/SSGに移行するか、有限のルートセットをプリレンダリングします。確認: curlが主要なコンテンツとリンクを返すことを確認します。
直接ルートリクエストが404を返す
考えられる原因: Vue Routerのヒストリーモードにサーバーフォールバックがないか、デプロイメントが生成されたルートを省略している。修正: SPAのみのルートのホストリライトを設定するか、実際のSSR/静的ルート出力をデプロイします。確認: リフレッシュと直接リクエストが意図したステータスとページを返すことを確認します。
タイトルはブラウザでは更新されるが、ソースでは更新されない
考えられる原因: メタデータがクライアントのライフサイクルまたは非同期のブラウザフェッチに依存している。修正: SSR/SSG中にデータを解決し、@unhead/vueまたはNuxtのhead APIでheadタグをレンダリングします。確認: 生とレンダリングされたタイトル、正規化、robotsディレクティブが一致することを確認します。
ハイドレーションが正しいサーバーコンテンツを置き換える
考えられる原因: サーバー/クライアントのデータまたは環境の分岐が一致していない。修正: 初期データを決定的にし、必須マークアップからブラウザのみの条件を削除する。確認: ハイドレーションが不一致警告なしで完了し、インデックス可能なコンテンツが変更されないことを確認する。
Vueの生の出力とレンダリングされた出力を比較する
curl -fsSL https://example.com/page/ > raw.html
grep -Eio '<title>[^<]+|<h1[^>]*>[^<]+|<link[^>]+rel="canonical"[^>]*' raw.htmlハイドレーション後にDevToolsコンソールでこれを実行します:
({title: document.title, h1: document.querySelector('h1')?.textContent.trim(), canonical: document.querySelector('link[rel="canonical"]')?.href, links: [...document.querySelectorAll('a[href]')].length});重要な値がコンソールの結果にのみ存在する場合、SSR/プリレンダリングは不完全です。
ハッシュベースのコンテンツリンクを見つける
[...document.querySelectorAll('a[href^="#"]')].map(a => ({text: a.textContent.trim(), href: a.getAttribute('href')}));リストを手動で確認します: ページ内ナビゲーションは問題ありません。フラグメントを別のコンテンツルートとして使用することが問題です。
Vue SEOのためのツール
- URL Inspection (Google Search Console) — 真実の情報源。ライブテストを実行し、レンダリングされたHTML、スクリーンショット、ページリソース(JS/CSSがブロックされていないか?)、コンソールメッセージを確認します。これにより、Vueのコンテンツ、メタ、JSON-LDが実際にレンダリングされたことを確認できます。
- リッチリザルトテスト — サイトを検証せずに、単一のURLに対して高速なレンダリング済みHTML + 構造化データチェックを行います。
- Chrome DevTools — ソースを表示(生のHTML、レンダリングしないボットが見るもの)と要素パネル(ハイドレーションされたDOM)を比較します。コンソールにはハイドレーション不一致警告が表示されます。
- Vue Devtools — クライアントのみとサーバーレンダリングの違いをデバッグしながら、コンポーネントの状態とルーターモードを検査します。
vite-ssg— コンテンツが安定したVue 3 SPA向けのビルド時プリレンダリング(vite build→vite-ssg buildに置き換え)。- JavaScriptレンダリングクローラー — Ahrefs Site AuditとScreaming Frog(JSレンダリングモード)はJSを実行するため、Vueサイト全体で生の出力とレンダリングされた出力を比較できます。
- Lighthouse / PageSpeed Insights — CSRバンドルがLCPとCore Web Vitalsのレバー(コード分割、遅延ルート、画像の優先順位)に与える影響を検出します。
自分をテスト: Vue SEO
Vueアプリをクロール可能かつインデックス可能にするための5つの簡単な質問。各質問に回答を選び、確認してください。
時間をかける価値のあるリソース
私の記事
- JavaScript SEO: A Definitive Guide — レンダリング、DOMパリティ、フレームワークレベルの決定に関する完全ガイド。Vue Routerのhistoryモードとhashモードの比較と、私のJS正規化テストを含みます。
- The Beginner’s Guide to Technical SEO — レンダリングとJavaScript SEOが全体像の中でどのように位置づけられるか。
私の講演
- 検索の仕組み (SlideShare)— クロール、レンダリング、インデックス、ランキングの解説。(いつもの免責事項が適用されます:“This is based on my understanding of the systems… it may not be 100% complete or accurate.” (翻訳) 「これは私のシステム理解に基づくものであり……100% 完全または正確とは限りません。」)
業界の情報源
- Server-Side Rendering (SSR) | Vue.js — 公式ガイド: SSRのSEO上の利点、非同期の注意点、SSGを選ぶべきタイミング。
- Different History modes | Vue Router — ハッシュモードがSEOに悪影響を与える理由と、historyモードの設定方法。
- useSeoMeta() · Unhead — 現在の
@unhead/vueメタAPI。 - antfu-collective/vite-ssg | GitHub — Vue 3 SPA向けのビルド時プリレンダリング。
- Site Config | VitePress — Vueベースのドキュメントサイト向けSEO。
- How Nuxt.js solves the SEO problems in Vue.js | LogRocket — SSR/SSGパスとしてNuxtを選ぶ理由。
- Google no longer recommends using dynamic rendering | Search Engine Land — 動的レンダリングの非推奨化に関する報道。
- Vue.js And SEO: How To Optimize Reactive Websites | Smashing Magazine — 広く引用される2019年の記事。非同期タイミングの実験に有用ですが、ツールに関しては古い(evergreen以前のChromium)。
動画
変更履歴
2026年8月22日に更新。
編集概要と記録された変更の詳細。変更の詳細
-
変更の詳細な注記は現在英語でのみ提供されています。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。
2026年7月18日に更新。
編集概要と記録された変更の詳細。変更の詳細
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。