JavaScript SEO
JavaScript SEO 研究爬蟲如何抓取與執行 JS。關鍵是提供可索引的 HTML(SSR/SSG/prerender)與正確的 meta/schema。
定義
JavaScript SEO 是針對使用 JavaScript 框架(React/Vue/Svelte)網站的可索引性策略。純 CSR(SPA)需要爬蟲下載 JS、執行再產生 DOM,過程慢且不穩;最可靠的解法是 SSR 或 build-time prerender(SSG),讓每個路徑一開始就有完整 HTML。
為什麼重要
- 降低爬蟲成本:不必等 JS 執行就能理解內容,Googlebot render queue 有限
- 避免收錄延遲:純 CSR 容易出現『看得到但搜不到』的窘境
- 讓 metadata/結構化資料在第一時間可讀,提升 SEO/AEO 穩定性
- 確保社群分享正確:Facebook/Twitter 爬蟲不執行 JS,OG tags 需在初始 HTML
- 提升 Core Web Vitals:LCP 依賴有意義的 HTML 而非等待 JS bundle 載入
- 支援 AI 引擎索引:ChatGPT/Perplexity 的爬蟲渲染能力有限
- 降低 soft 404 風險:動態路由若未正確處理,爬蟲可能誤判為空頁面
怎麼做(實作重點)
- 優先提供 per-route HTML:SSR 或 SSG/prerender,避免純 CSR
- 確保 head tags 正確:title/description/canonical/hreflang/schema 都在初始 HTML
- 檢查渲染結果:用 View Source、Search Console URL Inspection、Rich Results Test
- 設定正確的 HTTP 狀態碼:404 頁面回 404,不要 200 OK 配空內容
- 處理 lazy loading:確保主要內容不需滾動就可見於 HTML
- 避免 hydration mismatch:SSR/SSG 輸出與 CSR 結果必須一致
- 監控 Crawl Stats:Search Console 的抓取統計可看出渲染問題
範例
typescript
// vite.config.ts - 使用 vite-plugin-ssr 或 vite-ssg
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
// 搭配 prerender script
// node scripts/prerender.js
});
// scripts/prerender.js
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom/server';
import App from '../src/App';
const routes = ['/glossary/javascript-seo', '/glossary/ssr'];
for (const route of routes) {
const html = renderToString(
<StaticRouter location={route}>
<App />
</StaticRouter>
);
// 寫入 dist/[route]/index.html
}typescript
// src/components/SEOHead.tsx
import { Helmet } from 'react-helmet-async';
interface SEOHeadProps {
title: string;
description: string;
canonical: string;
schema?: object;
}
export function SEOHead({ title, description, canonical, schema }: SEOHeadProps) {
return (
<Helmet>
<title>{title}</title>
<meta name="description" content={description} />
<link rel="canonical" href={canonical} />
{schema && (
<script type="application/ld+json">
{JSON.stringify(schema)}
</script>
)}
</Helmet>
);
}
// 使用:確保 SSR 時 Helmet 也被正確 render
// renderToString 後呼叫 helmet.renderStatic()相關連結
常見問題
關於這個詞彙的常見問答。