傳統的 Web 頁面,一般是服務端渲染的,而隨着 SPA(Single-Page Application) 尤爲是 React、Vue、Angular 爲表明的前端框架的流行,愈來愈多的 Web App 使用的是客戶端渲染。html
使用客戶端渲染有着諸多優點,好比節省後端資源、局部刷新、先後端分離等等,但也帶來了一些挑戰,好比本文要解決的 SEO 問題。前端
對於服務端渲染的頁面,服務端能夠直接將內容經過 HTML 的形式返回,搜索引擎爬蟲能夠輕易的獲取頁面內容,而對於客戶端渲染的應用,客戶端必須執行服務器返回的 Javascript 才能獲得正確的網頁內容。目前,除 Google、Bing 支持 Javascript 外(也會有一些限制),其餘的大部分搜索引擎都不支持 Javascript,也就沒法獲取正確的網頁內容。git
Google 推出的 Rendertron 就是爲了解決這樣場景的一款工具。經過使用 Rendertron,SPA 也可以被不支持執行 Javascript 的搜索引擎爬取渲染後的內容。其原理主要是經過使用 Headless Chrome 在內存中執行 Javascript,並在獲得完整內容後,將內容返回給客戶端。github
一般會將 Rendertron 部署爲一個獨立的 HTTP 服務,而後爲 Web 應用框架配置 Google 官方提供的中間件或者在反向代理上添加相應路由規則,使得可以在檢測到搜索引擎爬蟲的 UA 時,能夠將請求代理給 Rendertron 服務。docker
Rendertron 提供了兩個主要 API,分別是 Render 以及 Screenshot。其中 Render 用於渲染網站內容,Screenshot 用於將網站內容截圖。在 SEO 場景下使用的是 Render 接口。shell
舉例來講,當客戶端請求咱們的網站時,咱們搜線根據請求頭 User Agent 發現包含了 Baiduspider/2.0 關鍵字,能夠認定爲當前的客戶端是一個百度爬蟲,而後又在 UserAgent 中發現 Mobile 關鍵字,能夠認定這個爬蟲是在作移動端內容的抓取。經過上面的判斷,就能夠將這個請求代理 Rendertron 服務的 /render/https://www.aliyun.com/?mobile
路由,讓 Rendertron 幫助執行網頁內的 Javascript,並將最終內容返回給搜索引擎爬蟲。npm
Google 官方提供了示例 https://render-tron.appspot.com/ ,能夠直接體驗效果。bootstrap
咱們也提供了部署在函數計算上的示例:http://renderton.mofangdegisn.cn後端
基於函數計算,咱們的服務架構以下:瀏覽器
這裏咱們選擇阿里雲的性能測試PTS服務進行壓測。
測試配置以下:
咱們配置了 100 併發,測試 6 分鐘,每分鐘併發按照 20% 遞增的規則進行壓測。
咱們要測試的網址網站爲:http://renderton.mofangdegisn.cn/render/https://www.example.com/
該網址表示讓 rendertron 請求 https://www.example.com/ 這個網站的內容,並返回渲染結果。
測試概覽以下:
從上面的概覽能夠看到,因爲會發生從函數到 https://www.example.com/ 的網絡請求,因此最小延遲爲 1106ms,99% 的請求能夠在 2011ms 完成,90% 的請求能夠在 1347ms 完成,75% 的請求能夠在 1201ms 完成,50% 的請求能夠在 1156ms 完成。咱們是每分鐘按照 20% 的併發遞增,當併發增長時,函數計算會遇到冷啓動,冷啓動最大時間爲 32261ms(可使用預熱、預留等方式能夠緩解或徹底免除冷啓動的影響)。
在未優化的場景下,咱們的壓測結果也達到了 44.91 的 TPS,這對於大部分網站是絕對可以知足需求的。
壓測明細以下:
上面箭頭所指的位置表示併發忽然增長,函數自動擴容時會遇到一些冷啓動,當擴容完畢,後續的請求就很是平穩了。
將 Rendertron 部署到傳統的 ECS 或者物理機上做爲生產服務,並非件容易的事。除了 Rendertron 自己須要一些安裝配置外,還須要考慮當流量增長時如何擴容,以及配置搭建反向代理或負載均衡等與之配套的服務。
下面,咱們介紹下函數計算如何解決這些問題的。
git clone https://github.com/GoogleChrome/rendertron.git
PS: 這裏直接基於官方項目進行改造,而不是提供一個示例模板,是爲了演示如何平滑遷移 rendertron 到函數計算,同時,在官方版本更新後,也能夠儘快更新到最新版本。
template.yml 是 Fun 默認的描述文件,經過該描述文件描述的資源,能夠經過 fun deploy 一鍵在部署到雲端。
好比,咱們下面的模板聲明瞭一個名爲 Rendertron 的服務以及名爲 rendertron 的函數。
函數是函數計算系統調度和代碼執行的基本單位,咱們的 rendertron 項目就能夠跑在函數裏,而服務是管理函數計算資源管理的單位,一個服務能夠包含多個函數。
對於初學者,能夠直接將下面的模板放在項目根目錄下,而且命名爲 template.yml。
ROSTemplateFormatVersion: '2015-09-01' Transform: 'Aliyun::Serverless-2018-04-03' Resources: Rendertron: # 聲明一個名爲 Rendertron 的服務 Type: 'Aliyun::Serverless::Service' Properties: Description: This is Rendertron service rendertron: # 聲明一個名爲 rendertron 的函數 Type: 'Aliyun::Serverless::Function' Properties: Handler: index.handler Runtime: custom # runtime,咱們使用 custom Timeout: 60 MemorySize: 1024 CodeUri: ./ Events: httpTrigger: # 添加 http 觸發器 Type: HTTP Properties: AuthType: ANONYMOUS Methods: - GET - POST - PUT renderton.mofangdegisn.cn: # 添加自定義域名 Type: 'Aliyun::Serverless::CustomDomain' Properties: Protocol: HTTP RouteConfig: routes: /*: ServiceName: Rendertron FunctionName: rendertron
接下來在項目根目錄建立一個名爲 bootstrap
的文件,這個文件告訴函數計算如何啓動 rendertron,文件內容以下:
#!/usr/bin/env bash PORT=9000 HOST=0.0.0.0 npm run start
直接使用 fun install -d
能夠一鍵安裝依賴,至關於官方文檔裏的 npm install,只不過,fun install -d
除了安裝 npm 依賴外,還能夠檢測到 rendertron 包含的 puppeteer 依賴,而且會自動安裝 puppeteer 所必須的 apt 依賴,更多細節能夠參考這篇文章:
fun install -d
接着使用官方介紹的 npm run build
編譯項目:
npm run build
不須要修改原項目中的代碼,咱們能夠直接經過 fun local start renderton.mofangdegisn.cn 在本地將函數啓動,而後經過瀏覽器訪問。
fun local start renderton.mofangdegisn.cn
演示效果以下:
當本地運行、調試確認沒有問題了,就能夠考慮部署到線上了。在部署前,要先將 template.yml 中的域名替換爲本身的。
這裏簡單介紹下步驟:假如本身 Aliyun 的 AccountId 爲 12345,那麼就將本身的域名(國內集羣須要備案)CNAME 到 12345.cn-shanghai.fc.aliyuncs.com,而後將本身的域名更新到 template.yml,執行 fun deploy 便可。更多詳情能夠參考這篇文檔。
最後使用 fun deploy 一鍵部署便可。
使用 Rendertron + 函數計算能夠快速搭建一個能夠直接用於生產的 Headless Chrome 渲染解決方案,以便於幫助網站更好的進行 SEO。
「 阿里巴巴雲原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,作最懂雲原生開發者的技術圈。」