隨着react、vue、angular等前端框架的流行愈來愈多的web應用變成了單頁應用,它們的特色是異步拉取數據在瀏覽器中渲染出HTML。使用這些框架極大的提高web用戶體驗和開發效率的同時缺帶來一個新問題,那就是這樣的網頁沒法被搜索引擎收錄。雖然這些web框架支持服務端渲染,但這可能又會增長開發成本。html
有沒有一個可用於任何單頁應用的SEO解決方案,讓咱們不用對代碼作改變保持原有的開發效率?chrome-render能夠幫咱們作到這點,它經過控制HeadlessChrome渲染出最終的HTML返回給爬蟲來實現。前端
前不久chrome團隊宣佈chrome支持headless模式,HeadlessChrome支持chrome所具備的全部功能只不過由於不顯示界面而更快資源佔用更小。相比於以前的phantomjs(做者由於HeadlessChrome的推出而宣佈中止維護)chrome的優點在於它又一個很強的爹(google)會一直維護它優化它,而且chrome在用戶量、體驗、速度、穩定性都是第一的,因此我認爲HeadlessChrome會漸漸替代以前全部的HeadlessBrowser方案。vue
既然HeadlessChrome是以無界面模式運行的,那要怎麼控制它和它交互?
chrome提供了遠程控制接口,目前能夠經過chrome-remote-interface來用js代碼向chrome發送命令進行交互。在啓動chrome的時候要開啓遠程控制接口,而後經過 chrome-remote-interface 鏈接到chrome後再經過協議控制chrome。具體操做見文檔:react
chrome-render先會經過chrome-runner以headless模式啓動和守護你操做上的chrome,再經過chrome-remote-interface操控chrome去訪問須要被SEO的網頁讓chrome運行這個網頁,等到包含數據的HTML被渲染出來時讀取當前網頁DOM轉換成字符串後返回。chrome
怎麼知道你的網頁何時已經渲染出包含數據的HTML了能夠返回了呢?爲了提高chrome-render效率,默認會在domContentEventFired
時返回。對於複雜的場景還能夠經過開啓chrome-render的useReady
選項,等到網頁裏調用了window.chromeRenderReady()
時返回。api
只渲染出了HTML還不夠咱們還須要檢測出來着搜索引擎爬蟲的訪問,若是請求來着爬蟲就返回chrome-render渲染後的HTML不然返回正常的單頁應用所需HTML。瀏覽器
綜上,總體架構以下:
只需如下幾行簡單代碼就可以讓chrome渲染出HTML:
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,要集成到你現有的項目很簡單,以下:
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,但願你們和我一塊兒來改進它們讓它們更強大。