跳至主要內容

    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()

    相關連結

    常見問題

    關於這個詞彙的常見問答。

    回到詞彙表