使用 HeadlessChrome 做單頁應用 SEO

發表於2017-07-03

隨著react、vue、angular等前端框架的流行越來越多的web應用變成了單頁應用,它們的特點是非同步拉取資料在瀏覽器中渲染出HTML。使用這些框架極大的提升web使用者體驗和開發效率的同時缺帶來一個新問題,那就是這樣的網頁無法被搜尋引擎收錄。雖然這些web框架支援服務端渲染,但這可能又會增加開發成本。

有沒有一個可用於任何單頁應用的SEO解決方案,讓我們不用對程式碼做改變保持原有的開發效率?chrome-render可以幫我們做到這點,它通過控制HeadlessChrome渲染出最終的HTML返回給爬蟲來實現。

HeadlessChrome介紹

前不久chrome團隊宣佈chrome支援headless模式,HeadlessChrome支援chrome所具有的所有功能只不過因為不顯示介面而更快資源佔用更小。相比於之前的phantomjs(作者因為HeadlessChrome的推出而宣佈停止維護)chrome的優勢在於它有一個很強的爹(google)會一直維護它優化它,並且chrome在使用者量、體驗、速度、穩定性都是第一的,所以我認為HeadlessChrome會漸漸替代之前所有的HeadlessBrowser方案。

如何操控HeadlessChrome

既然HeadlessChrome是以無介面模式執行的,那要怎麼控制它和它互動?
chrome提供了遠端控制介面,目前可以通過chrome-remote-interface來用js程式碼向chrome傳送命令進行互動。在啟動chrome的時候要開啟遠端控制介面,然後通過 chrome-remote-interface 連線到chrome後再通過協議控制chrome。具體操作見文件:

chrome-render原理與實踐

原理

chrome-render先會通過chrome-runner以headless模式啟動和守護你操作上的chrome,再通過chrome-remote-interface操控chrome去訪問需要被SEO的網頁讓chrome執行這個網頁,等到包含資料的HTML被渲染出來時讀取當前網頁DOM轉換成字串後返回。

怎麼知道你的網頁什麼時候已經渲染出包含資料的HTML了可以返回了呢?為了提升chrome-render效率,預設會在domContentEventFired時返回。對於複雜的場景還可以通過開啟chrome-render的useReady選項,等到網頁裡呼叫了window.chromeRenderReady()時返回。

只渲染出了HTML還不夠我們還需要檢測出來著搜尋引擎爬蟲的訪問,如果請求來著爬蟲就返回chrome-render渲染後的HTML否則返回正常的單頁應用所需HTML。

綜上,整體架構如下:
koa-seo arch

實踐

只需以下幾行簡單程式碼就可讓chrome渲染出HTML:

chrome-render只是做了渲染出HTML的工作,要實現SEO還需要和web伺服器整合。為了方便大家使用我做了一個koa中介軟體koa-seo,要整合到你現有的專案很簡單,如下:

只需像這樣接入一箇中介軟體你的單頁應用就被SEO了。

應用場景擴充套件

chrome-render除了用於通用SEO解決方案其實可以用於通用服務端渲染,因為目的都是渲染出最終的HTML再返回。針對通用服務端渲染我也做了一個koa中介軟體koa-chrome-render。使用chrome-render做服務端渲染的

優勢在於:

  • 通用,適用於所有單頁應用
  • 對原有程式碼幾乎無改動,最多再合適的地方加個window.chromeRenderReady(),保持原有開發效率

缺點在於:

  • 和react、vue等只帶的服務端渲染相比效能低(經我測試大約 200ms vs 60ms)
  • chrome-render渲染時佔用資源高,一次渲染大約佔用25Mb記憶體,當請求量大時伺服器可能扛不住。但是可以通過快取渲染結果優化。

總結

大家可能會說這個很像prerender.io,沒錯思路是一樣的,chrome-render的優勢在於:

  • chrome-render開源可自己部署,prerender要收費是商業產品
  • prerender基於已經停止維護的phantomjs

本文中所提到的相關專案都是開源的並且有詳細的使用文件,它們的文件連結如下:

喜歡的給個star,希望大家和我一起來改進它們讓它們更強大。

相關文章