傳統(tǒng)的 Web 頁面,通常是服務(wù)端渲染的,而隨著 SPA(Single-Page Application) 尤其是 React、Vue、Angular 為代表的前端框架的流行,越來越多的 Web App 使用的是客戶端渲染。
站在用戶的角度思考問題,與客戶深入溝通,找到李滄網(wǎng)站設(shè)計(jì)與李滄網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗(yàn)好的作品,建站類型包括:網(wǎng)站制作、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名與空間、虛擬主機(jī)、企業(yè)郵箱。業(yè)務(wù)覆蓋李滄地區(qū)。
使用客戶端渲染有著諸多優(yōu)勢,比如節(jié)省后端資源、局部刷新、前后端分離等等,但也帶來了一些挑戰(zhàn),比如本文要解決的 SEO 問題。
對于服務(wù)端渲染的頁面,服務(wù)端可以直接將內(nèi)容通過 HTML 的形式返回,搜索引擎爬蟲可以輕易的獲取頁面內(nèi)容,而對于客戶端渲染的應(yīng)用,客戶端必須執(zhí)行服務(wù)器返回的 Javascript 才能得到正確的網(wǎng)頁內(nèi)容。目前,除 Google、Bing 支持 Javascript 外(也會有一些限制),其他的大部分搜索引擎都不支持 Javascript,也就無法獲取正確的網(wǎng)頁內(nèi)容。
Google 推出的 Rendertron 就是為了解決這樣場景的一款工具。通過使用 Rendertron,SPA 也能夠被不支持執(zhí)行 Javascript 的搜索引擎爬取渲染后的內(nèi)容。其原理主要是通過使用 Headless Chrome 在內(nèi)存中執(zhí)行 Javascript,并在得到完整內(nèi)容后,將內(nèi)容返回給客戶端。
通常會將 Rendertron 部署為一個獨(dú)立的 HTTP 服務(wù),然后為 Web 應(yīng)用框架配置 Google 官方提供的中間件或者在反向代理上添加相應(yīng)路由規(guī)則,使得能夠在檢測到搜索引擎爬蟲的 UA 時,可以將請求代理給 Rendertron 服務(wù)。
Rendertron 提供了兩個主要 API,分別是 Render 以及 Screenshot。其中 Render 用于渲染網(wǎng)站內(nèi)容,Screenshot 用于將網(wǎng)站內(nèi)容截圖。在 SEO 場景下使用的是 Render 接口。
舉例來說,當(dāng)客戶端請求我們的網(wǎng)站時,我們搜線根據(jù)請求頭 User Agent 發(fā)現(xiàn)包含了 Baiduspider/2.0 關(guān)鍵字,可以認(rèn)定為當(dāng)前的客戶端是一個百度爬蟲,然后又在 UserAgent 中發(fā)現(xiàn) Mobile 關(guān)鍵字,可以認(rèn)定這個爬蟲是在做移動端內(nèi)容的抓取。通過上面的判斷,就可以將這個請求代理 Rendertron 服務(wù)的 /render/https://www.aliyun.com/?mobile
路由,讓 Rendertron 幫助執(zhí)行網(wǎng)頁內(nèi)的 Javascript,并將最終內(nèi)容返回給搜索引擎爬蟲。
Google 官方提供了示例 https://render-tron.appspot.com/ ,可以直接體驗(yàn)效果。
我們也提供了部署在函數(shù)計(jì)算上的示例:http://renderton.mofangdegisn.cn
基于函數(shù)計(jì)算,我們的服務(wù)架構(gòu)如下:
這里我們選擇阿里云的性能測試PTS服務(wù)進(jìn)行壓測。
測試配置如下:
我們配置了 100 并發(fā),測試 6 分鐘,每分鐘并發(fā)按照 20% 遞增的規(guī)則進(jìn)行壓測。
我們要測試的網(wǎng)址網(wǎng)站為:http://renderton.mofangdegisn.cn/render/https://www.example.com/
該網(wǎng)址表示讓 rendertron 請求 https://www.example.com/ 這個網(wǎng)站的內(nèi)容,并返回渲染結(jié)果。
測試概覽如下:
從上面的概覽可以看到,由于會發(fā)生從函數(shù)到 https://www.example.com/ 的網(wǎng)絡(luò)請求,所以最小延遲為 1106ms,99% 的請求可以在 2011ms 完成,90% 的請求可以在 1347ms 完成,75% 的請求可以在 1201ms 完成,50% 的請求可以在 1156ms 完成。我們是每分鐘按照 20% 的并發(fā)遞增,當(dāng)并發(fā)增加時,函數(shù)計(jì)算會遇到冷啟動,冷啟動最大時間為 32261ms(可以使用預(yù)熱、預(yù)留等方式可以緩解或完全免除冷啟動的影響)。
在未優(yōu)化的場景下,我們的壓測結(jié)果也達(dá)到了 44.91 的 TPS,這對于大部分網(wǎng)站是絕對能夠滿足需求的。
壓測明細(xì)如下:
上面箭頭所指的位置表示并發(fā)突然增加,函數(shù)自動擴(kuò)容時會遇到一些冷啟動,當(dāng)擴(kuò)容完畢,后續(xù)的請求就非常平穩(wěn)了。
將 Rendertron 部署到傳統(tǒng)的 ECS 或者物理機(jī)上作為生產(chǎn)服務(wù),并不是件容易的事。除了 Rendertron 本身需要一些安裝配置外,還需要考慮當(dāng)流量增加時如何擴(kuò)容,以及配置搭建反向代理或負(fù)載均衡等與之配套的服務(wù)。
下面,我們介紹下函數(shù)計(jì)算如何解決這些問題的。
git clone https://github.com/GoogleChrome/rendertron.git
PS: 這里直接基于官方項(xiàng)目進(jìn)行改造,而不是提供一個示例模板,是為了演示如何平滑遷移 rendertron 到函數(shù)計(jì)算,同時,在官方版本更新后,也可以盡快更新到最新版本。
template.yml 是 Fun 默認(rèn)的描述文件,通過該描述文件描述的資源,可以通過 fun deploy 一鍵在部署到云端。
比如,我們下面的模板聲明了一個名為 Rendertron 的服務(wù)以及名為 rendertron 的函數(shù)。
函數(shù)是函數(shù)計(jì)算系統(tǒng)調(diào)度和代碼執(zhí)行的基本單位,我們的 rendertron 項(xiàng)目就可以跑在函數(shù)里,而服務(wù)是管理函數(shù)計(jì)算資源管理的單位,一個服務(wù)可以包含多個函數(shù)。
對于初學(xué)者,可以直接將下面的模板放在項(xiàng)目根目錄下,并且命名為 template.yml。
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
Rendertron: # 聲明一個名為 Rendertron 的服務(wù)
Type: 'Aliyun::Serverless::Service'
Properties:
Description: This is Rendertron service
rendertron: # 聲明一個名為 rendertron 的函數(shù)
Type: 'Aliyun::Serverless::Function'
Properties:
Handler: index.handler
Runtime: custom # runtime,我們使用 custom
Timeout: 60
MemorySize: 1024
CodeUri: ./
Events:
httpTrigger: # 添加 http 觸發(fā)器
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
接下來在項(xiàng)目根目錄創(chuàng)建一個名為 bootstrap
的文件,這個文件告訴函數(shù)計(jì)算如何啟動 rendertron,文件內(nèi)容如下:
#!/usr/bin/env bash
PORT=9000 HOST=0.0.0.0 npm run start
直接使用 fun install -d
可以一鍵安裝依賴,相當(dāng)于官方文檔里的 npm install,只不過,fun install -d
除了安裝 npm 依賴外,還可以檢測到 rendertron 包含的 puppeteer 依賴,并且會自動安裝 puppeteer 所必須的 apt 依賴,更多細(xì)節(jié)可以參考這篇文章:
fun install -d
接著使用官方介紹的 npm run build
編譯項(xiàng)目:
npm run build
不需要修改原項(xiàng)目中的代碼,我們可以直接通過 fun local start renderton.mofangdegisn.cn 在本地將函數(shù)啟動,然后通過瀏覽器訪問。
fun local start renderton.mofangdegisn.cn
演示效果如下:
當(dāng)本地運(yùn)行、調(diào)試確認(rèn)沒有問題了,就可以考慮部署到線上了。在部署前,要先將 template.yml 中的域名替換為自己的。
這里簡單介紹下步驟:假如自己 Aliyun 的 AccountId 為 12345,那么就將自己的域名(國內(nèi)集群需要備案)CNAME 到 12345.cn-shanghai.fc.aliyuncs.com,然后將自己的域名更新到 template.yml,執(zhí)行 fun deploy 即可。更多詳情可以參考這篇文檔。
最后使用 fun deploy 一鍵部署即可。
使用 Rendertron + 函數(shù)計(jì)算可以快速搭建一個可以直接用于生產(chǎn)的 Headless Chrome 渲染解決方案,以便于幫助網(wǎng)站更好的進(jìn)行 SEO。
“阿里巴巴云原生關(guān)注微服務(wù)、Serverless、容器、Service Mesh 等技術(shù)領(lǐng)域、聚焦云原生流行技術(shù)趨勢、云原生大規(guī)模的落地實(shí)踐,做最懂云原生開發(fā)者的技術(shù)圈?!?/p>