單頁面(如react,vue)網站的服務器渲染 SSR 之 SEO 大殺器 Rendertron

單頁面網站,好比vue、recat框架的網站,通常都是直接從服務器推送index.html,再根據自身路由經過js在客戶端瀏覽器渲染出完整的html頁面。css

可是搜索引擎的爬蟲可沒有這麼智能(實際上google就有這麼智能,拿到js文件自動幫你渲染好,但身在CN,將就下百度這個阿斗吧),爲了SEO,要想爬蟲爬到你的網站的內容,就得先由服務器把頁面渲染好後再發送給爬蟲,這就尷尬了,傳統的服務器渲染是多頁面的,一個請求對應一個頁面,但SPA不是啊,原本就一個單頁面,你叫我寫各類路由對應渲染好了再給你??固然也不是不能夠,如下就是幾種方案:html

react自帶的renderToStringvue

react自帶的renderToString 和 renderToStaticMarkup 就能夠用來將組件(Virtual DOM)輸出成 HTML 字符串,看起來不錯,可是要本身配參數啊,webpack不會怎麼辦,本來路由寫在一塊兒怎麼辦,redux要改動怎麼辦,若是這些你都ok的話,react自帶的方案也是一種不錯的選擇,這裏就很少說了,網上相關帖子不少。node

nextjsreact

還有一種方案,就更尷尬了,叫nextjs框架(nextjs是react的,vue的叫nuxtjs),這種框架寫出來直接就是多頁面的,也就是用react的語法和規則,寫出多頁面網站來,每一個頁面的入口名字就是路由名字,服務器也是nextjs自帶的,短短几行就能把單個網頁渲染好並推送出去,是否是看起來棒棒的?!linux

那爲啥說尷尬呢?就是由於他雖然說跟react很像,但仍是一個新框架,你不得不花時間學一下nextjs;他的路由對應頁面文件,這種路由看似簡單明瞭,可是一點都不自由;nextjs是多頁面的,好不容易進化到單頁面,你讓我再回到中世紀?原罪啊!因此若是你已經寫好了一個單頁面網站,要改爲nextjs框架的話,我只能說呵呵了,這返工返的……webpack

rendertrongit

咱們的主角要出場了!rendertron的由來我很少說了,當初誕生就是爲了作SEO的。先說說原理,聽完你就知道是個好東西了。github

Rendertron是nodejs框架下的產物,是google-chrome旗下的的配套產品。首先,服務器上裝有個google-chrome,rendertron把他打開,而後在服務器(官方推薦express)中增長中間件,先判斷UA(user-agent)裏面有沒有帶有相似Baiduspider(百度爬蟲)等字樣,若是沒有,就像正常的單頁面服務器那樣,把原始html推送出去,由客戶端瀏覽器完成js、css渲染的工做;若是帶有指定UA頭字樣,就先把網頁推送給本地服務器那個google-chrome,等他渲染好對應頁面後,把渲染好的html結果推送出去。不就是爲了SEO麼,你爬蟲來了我再渲染給你總行了吧,其他的我仍是作個人單頁面,呵呵噠。web

圖片描述

下面上一張圖,說明原理。(原理跟rendora的差很少,下圖的rendora你把他換成rendertron就行了)

好了,如今講講怎麼用,官網有用法,我給個連接rendertron官網。可是這裏我講一下具體怎麼用的一種無腦方案,你照作就能夠了,另外官網demo還有很多的坑和bug,我也挑出來和你們分享一下。

安裝Chromeheadless

先在你的服務器上安裝Chromeheadless,這是服務器上的無頭chrome瀏覽器,若是你的服務器上已經有這個,那恭喜你了,由於安裝過程的坑實在是太多太多了。網上關於安裝Chromeheadless的教學貼不少,在此我貼幾個。

先在你的服務器上安裝Chromeheadless,這是服務器上的無頭chrome瀏覽器,若是你的服務器上已經有這個,那恭喜你了,由於安裝過程的坑實在是太多太多了。網上關於安裝Chromeheadless的教學貼不少,在此我貼幾個:

安裝過程當中你會遇到不少坑,不過沒關係,把error複製粘貼一下放百度,仍是有不少解決方案的,畢竟Chromeheadless不是什麼小衆的東西

安裝rendertron

直接命令行輸入

npm install -g rendertron

回車,就裝好了。就這麼簡單?呵呵,有greatWall,安裝過程當中必需的某個東東下載不了,這時候要用代理,會的同窗固然ok,可是不會的同窗就沒辦法了,我本身一臺大陸一臺海外,大陸的裝不了就改海外服務器了。

還有一個方案,也是官方給出的:

git clone https://github.com/GoogleChrome/rendertron.git
cd rendertron
npm install
npm run build

運行:

npm run start

能用第一種安裝方案的推薦用第一種。

在你的express服務器程序中引入中間件rendertron-middleware

進入項目目錄,命令行輸入並回車

npm install --save express rendertron-middleware

在你的express服務器程序的代碼中加入幾行:

const express = require('express');const rendertron = require('rendertron-middleware');
const app = express();
app.use(rendertron.makeMiddleware({
  proxyUrl: 'http://localhost:3000/render',}));
app.use(express.static('files'));app.listen(8080);

重點是插入的

app.use(rendertron.makeMiddleware({
  proxyUrl: 'http://localhost:3000/render',}));

其中rendertron.makeMiddleware有好幾個參數,github上說有

proxyUrl、userAgentPattern、excludeUrlPattern、injectShadyDom、timeout,也就是有相似如下的設置。
app.use(rendertron.makeMiddleware({
  proxyUrl: 'http://localhost:3000/render',
  userAgentPattern:****,
  excludeUrlPattern:****,
  injectShadyDom:true or false, //這個參數通常不用設,用的時候這行刪掉就行了  timeout:11000,//這個timeout超時參數親測已經無效了,尷尬,用的時候也去掉這行就好}));

下面重點講講以上的userAgentPattern和excludeUrlPattern參數的含義和怎麼設置。
userAgentPattern是用來寫清楚哪些UA頭須要服務器渲染,除此以外的請求都直接單頁面推送。好比說:

const botUserAgents = [
  'Baiduspider',
  'bingbot',
  'Embedly',
  'facebookexternalhit',
  'LinkedInBot',
  'outbrain',
  'pinterest',
  'quora link preview',
  'rogerbot',
  'showyoubot',
  'Slackbot',
  'TelegramBot',
  'Twitterbot',
  'vkShare',
  'W3C_Validator',
  'WhatsApp',];//略n行代碼app.use(rendertron.makeMiddleware({
    //其餘參數  userAgentPattern: new RegExp(botUserAgents.join('|'), 'i'),}));

把你要的爬蟲UA頭都寫到一個數組裏,而後用new RegExp()正則一下
excludeUrlPattern是指哪些文件格式須要在chromeheadless中被徹底加載,用法以下

const staticFileExtensions = [
  'ai', 'avi', 'css', 'dat', 'dmg', 'doc', 'doc', 'exe', 'flv',
  'gif', 'ico', 'iso', 'jpeg', 'jpg', 'js', 'less', 'm4a', 'm4v',
  'mov', 'mp3', 'mp4', 'mpeg', 'mpg', 'pdf', 'png', 'ppt', 'psd',
  'rar', 'rss', 'svg', 'swf', 'tif', 'torrent', 'ttf', 'txt', 'wav',
  'wmv', 'woff', 'xls', 'xml', 'zip',];//略n行代碼app.use(rendertron.makeMiddleware({
    //其餘參數  userAgentPattern: new RegExp(`\\.(${staticFileExtensions.join('|')})$`, 'i'),}));

把你須要加載的文件後綴都寫到一個數組裏,而後用new RegExp()正則一下

至於proxyUrl參數的用法,若是rendertron+chromeheadless在本地服務器,那就寫'http://localhost:3000/render'(rendertron啓動後默認開啓3000端口),若是是在別的服務器,那就寫http://www.xxxx.com/render或...://106.xx.xx.xxx:xxxx/render。

proxyUrl參數設置的就是遇到爬蟲UA頭後、轉到rendertron用本地服務器上的chromeheadless瀏覽器渲染的地址。

好了,express服務器改寫好後,正常啓動他,而後再啓動rendertron,方法也很簡單,直接命令行輸入rendertron就好了。

下面測試一下,命令行輸入curl -A 「baiduspider」 http://你須要測試的網址(就是訪問你的server程序對應的那個網址,即改寫前的那個原來的網址),而後就能看到經過chromeheadless渲染好的html代碼,大功告成!

rendertron的改進

有沒有發現你每次curl之後都須要10s左右後才能返回數據,這種響應時間怎麼可能用在SEO上呢??!!因此要改進一下咯。

在rendertron的github上有寫到,能夠在rendertron的根目錄寫一個config.json,裏面能夠設置datastoreCache(是否適用緩存,默認false),timeout(渲染超時,過了這個時間尚未渲染結束就硬性返回已渲染好的html,默認10000ms,即10s),port(端口,默認3000),width和height(渲染用的瀏覽器屏幕寬高,默認1000,這個在rendertron的另外一個功能‘截圖’上能夠用到)。

而後你很天真的設置了config.json文件,把timeout改爲3000ms——這差很少已是搜索引擎認爲你是優質網站所要求的響應時間的上限了。再一次curl,什麼!!仍是10s!!這個怎麼搞哦!!

又一次大寫的尷尬!下面來公佈答案吧~rendertron的碼源裏面已經沒有引用config.json裏面的timeout參數了,這個參數無法經過外部設置,呵呵噠,坑。

好了,下面說解決方法。找到rendertron根目錄,裏面有個build文件夾,裏面有個renderer.js文件,打開後,搜索timeout,一共有兩處,後面都跟了10000這個值,把它改爲你須要的2000或者之類的(單位ms),而後再次從新啓動rendertron,在命令行輸入

curl -A 「baiduspider」 http://你須要測試的網址(就是訪問你的server程序對應的那個網址,即改寫前的那個原來的網址)

能夠發現只須要2s就有html代碼返回了,搞定!

注:以上問題是針對 npm install -g rendertron方式安裝的rendertron,其餘方式安裝後是否有以上問題不必定。

若是你的渲染程序會崩,那就pm2 start rendertron。pm2真的挺好用,不熟悉的同窗百度下就行了,滿滿的資料。

原文連接:單頁面(如react,vue)網站的服務器渲染 SSR 之 SEO 大殺器 Rendertron

相關文章
相關標籤/搜索