索引分成兩波進行
Googlebot 會先擷取您的原始 HTML,並幾乎立即索引該初次回應中已經存在的任何內容。只有在 JavaScript 執行後才出現的內容,會被排入第二波 —— 也就是渲染 —— 這需要動用額外資源,比起初次爬取,延遲時間可能從幾秒到(在爬取資源有限的網站上)長得多不等。若您的內容或內部連結只在第二波之後才存在,等於是仰賴一條較慢、較不確定的路徑才能被索引。
真正會破壞索引的做法
- 主要內容或內部連結只在用戶端擷取後才渲染,初始 HTML 中沒有任何實質內容。
- 內容被鎖在需要使用者操作(點擊、捲動、滑鼠懸停)才會顯示,而 Googlebot 沒有理由執行這些操作。
- 頁面渲染所需的 JS 或 CSS 檔案被 robots.txt 封鎖;參閱robots.txt 與 noindex 的差異,了解封鎖可能如何適得其反。
- 前端路由從未實際改變 HTTP 狀態碼 —— 損壞的路由可能顯示空白或「找不到」訊息,卻仍傳回 200,這會被判定為soft 404。
- 只在無頭瀏覽器環境中才會發生的水合(hydration)或渲染錯誤,一般人工測試中不會被察覺。
如何檢查 Google 實際看到的內容
Search Console 的網址檢查工具有一個「已測試網頁」檢視畫面,會顯示 Google 渲染器執行後的實際 HTML 與截圖 —— 而不只是原始回應。將它與您的原始碼 HTML 進行比對:若關鍵內容或連結在原始回應中缺席、卻在渲染後才出現,代表您完全仰賴渲染佇列,而非速度較快的初次爬取。
真正有幫助的做法
- 對於攸關 SEO 的內容與導覽連結,採用伺服器端渲染(或靜態產生),而非於載入後才在用戶端擷取。
- 內部連結使用真正的
<a href>元素,而非在非錨點元素上綁定點擊事件 —— Googlebot 會跟隨 href,而不會執行任意的 JavaScript 事件綁定。 - 不要封鎖頁面渲染所依賴的 JS/CSS 套件 —— Google 需要擷取它們才能完整渲染頁面。
- 頁面修正後,不要只是等待下一次渲染排程 —— 直接要求重新建立索引,或透過 IndexNow 推送該網址,讓修正後的版本能依您自己的時程被處理,而非渲染器的排程。
各框架的注意事項
- 用戶端渲染的 React 應用程式:單純的單頁應用程式只會傳送幾乎空白的 HTML 外殼。對於需要取得排名的頁面,請使用支援伺服器端渲染或靜態產生的框架。
- Next.js 與 Nuxt:伺服器端渲染與靜態產生預設就會將內容放入初始 HTML。請留意只在用戶端 effect 中才載入的重要內容。
- Angular 與 Vue:請使用 Angular 的伺服器端渲染,或在 Vue 中使用 Nuxt,讓頁面送達時 HTML 中就已包含內容。
- 無限捲動:請搭配可獨立載入的分頁網址,讓爬蟲能觸及第一個畫面之後的項目。
今天就能做的快速測試
開啟頁面,選擇「檢視網頁原始碼」(而非「檢查」),然後搜尋主要內容中的一句話以及幾個內部連結網址。若原始碼中找不到它們,代表這些內容仰賴 JavaScript。接著執行免費的可索引性檢查,確認頁面傳回 200、未設定 noindex,且 canonical 正確。
常見問題
Google 能索引 JavaScript 內容嗎?
可以。Google 會使用新版的 Chrome 來渲染 JavaScript。問題在於時間與可靠性:渲染發生在初次爬取之後,而渲染過程中的錯誤可能導致內容遺漏。
Bing 和其他爬蟲會渲染 JavaScript 嗎?
Bing 也會渲染 JavaScript,但許多其他爬蟲(包括大多數社群媒體與 AI 爬蟲)只會讀取初始 HTML。伺服器端渲染能讓所有爬蟲都看得到您的內容。
現在還建議使用動態渲染嗎?
不建議。Google 將動態渲染(為機器人提供預先渲染的版本)定位為權宜之計,而非長期解決方案。建議的做法是伺服器端渲染或靜態產生。
每個頁面都需要伺服器端渲染嗎?
不需要。需要登入的頁面、資訊主頁,以及任何您不希望出現在搜尋結果中的內容,都可以維持用戶端渲染。請優先處理需要取得排名的頁面:到達網頁、文章,以及產品與分類頁面。
如何判斷索引問題是否由 JavaScript 造成?
在網址檢查的即時測試中,比較原始 HTML 與渲染後的 HTML。若關鍵內容或連結只在渲染後才出現,或渲染後的截圖看起來版面錯亂,JavaScript 很可能就是原因。