隨著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。
實踐
只需以下幾行簡單程式碼就可讓chrome渲染出HTML:
1 2 3 4 5 6 |
const ChromeRender = require('chrome-render'); ChromeRender.new().then(async(chromeRender)=>{ const htmlString = await chromeRender.render({ url: 'http://qq.com', }); }); |
chrome-render只是做了渲染出HTML的工作,要實現SEO還需要和web伺服器整合。為了方便大家使用我做了一個koa中介軟體koa-seo,要整合到你現有的專案很簡單,如下:
1 2 3 |
const seoMiddleware = require('koa-seo'); const app = new Koa(); app.use(seoMiddleware()); |
只需像這樣接入一箇中介軟體你的單頁應用就被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,希望大家和我一起來改進它們讓它們更強大。