React 服務端渲染方案完美的解決方案

小弟調調™發表於2019-03-04

最近在開發一個服務端渲染工具,通過一篇小文大致介紹下服務端渲染,和服務端渲染的方式方法。在此文後面有兩中服務端渲染方式的構思,根據你對服務端渲染的利弊權衡,你會選擇哪一種服務端渲染方式呢?

什麼是伺服器端渲染

使用 React 構建客戶端應用程式,預設情況下,可以在瀏覽器中輸出 React 元件,進行生成 DOM 和操作 DOM。React 也可以在服務端通過 Node.js 轉換成 HTML,直接在瀏覽器端“呈現”處理好的 HTML 字串,這個過程可以被認為 “同構”,因為應用程式的大部分程式碼都可以在伺服器和客戶端上執行。

為什麼使用伺服器端渲染

與傳統 SPA(Single Page Application - 單頁應用程式)相比,伺服器端渲染(SSR)的優勢主要在於:

  1. 更好的 SEO,由於搜尋引擎爬蟲抓取工具可以直接檢視完全渲染的頁面。
  2. 更好的使用者體驗,對於緩慢的網路情況或執行緩慢的裝置,載入完資源瀏覽器直接呈現,無需等待所有的 JavaScript 都完成下載執行,才顯示伺服器渲染的HTML。

服務端渲染的弊端

  1. 由於服務端與瀏覽器客戶端環境區別,選擇一些開源庫需要注意,部分庫是無法在服務端執行,比如你有 document、window 等物件獲取操作,都會在服務端就會報錯,所以在選擇的開源庫要做甄別

  2. 使用服務端渲染,比如要起一個專門在服務端渲染的服務,與之前,只管客戶端所需靜態資源不同,你還需要 Node.js 服務端的和運維部署的知識,對你所需要掌握的知識點要求更多

  3. 伺服器需要更多的負載,在 Node.js 中完成渲染,由於 Node.js 的原因大量的CPU資源會被佔用。

  4. 下文介紹一種服務端渲染的“操作”,這個新的操作擁有新的問題,比如API請求兩次,各種服務端問題,你就無能為力了,因為這個新的工具用Golang寫的,你的團隊或者是你,需要了解一下Golang,你說氣不氣人又要多學東西。

服務端渲染兩種方式

根據上文介紹對服務端渲染利弊有所瞭解,我們可以根據利弊權衡取捨,最近在做服務端渲染的專案,找到多種服務端渲染解決方案,大致分為兩類。

第一種方式

傳統方式服務端渲染,解決使用者體驗和更好的 SEO,有諸多工具使用這種方式如React的(Next.js)、Vue的(Nuxt.js)等。

有些工具將 webpack 執行在服務端生產環境,實時編譯,將編譯結果快取起來,這都還是傳統的方式,只不過將 webpack 執行在服務端實時編譯,還是開發環境編譯預編譯好的問題。

我選擇了將 webpack 放在開發環境,只做開發打包的功能,打包 客戶端 bundle服務端 bundle,資源對映檔案 assets.jsonCSS 等資源進行部署。

React 服務端渲染方案完美的解決方案

  • 伺服器 bundle 用於伺服器端渲染(SSR)
  • 客戶端 bundle 給瀏覽器載入,瀏覽器通過 bundle 載入更多其它模組(chunk)js
  • 資源對映檔案 assets.json 則是,伺服器 bundle 在準備所需 HTML,需要預插入那些模組(chunk)js,和CSS,這只是提高使用者體驗。

具體使用方法,可以看我最近造的個輪子 kkt-ssr,這個輪子將工具的部分封裝起來,你只需要寫業務程式碼,和少量的服務端渲染程式碼即可,還附贈十幾個示例,加上一個相對比較完善的示例react-router+rematch,類似於 next.js,但是有相當大的區別。

第二種方式

這是一種創新的方法,前端單頁面應用,以前怎麼玩兒,現在還怎麼玩兒,多的一步是,你得先訪問一個Rendora的服務,在前面攔截是否需要服務端渲染。下圖為官方圖:

React 服務端渲染方案完美的解決方案

這種方式原本只是個想法,想法是前端不用管服務端渲染的事兒了,不就是解決SEO?,這些爬蟲過來的時候,可以通過頭資訊判斷,寫個服務,然後將需要的內容給爬蟲就可以了,昨天恰巧在GitHub的趨勢榜上,恰巧看到 Rendora 個工具,也就那麼巧,剛好思路一致,這個工具主要為網路爬蟲提供零配置伺服器端渲染,以便毫不費力地改進在現代Javascript框架(如React.js,Vue.js,Angular.js等)中開發的網站的SEO問題。

React 服務端渲染方案完美的解決方案

這種方式非常好,之前寫好的專案一句不用改,只需新起 Rendora 服務。對於來自前端伺服器或外部的每個請求(百度谷歌爬蟲),Rendora會根據配置檔案,根據頭,路徑來檢測或過濾,以確定 Rendora 是否應該只傳遞從後端伺服器返回的初始HTML或使用Chrome提供的無頭伺服器端呈現的HTML。更具體地說,對於每個請求,有2條路徑:

  1. 請求被列入白名單作為SSR的候選者(即過濾後的Get請求),Rendora 會指示無頭Chrome例項請求相應的頁面,呈現它,並返回包含最終伺服器端的響應呈現出HTML。通常只需要將百度、谷歌、必應爬蟲等網路抓取工具列入白名單即可。
  2. 未列入白名單(即請求不是GET請求或未通過任何過濾器),Rendora將只是充當反向HTTP代理,只是按原樣傳送請求和響應。

Rendora可以看作是位於後端伺服器(例如Node.js / Express.js,Python / Django等等)之間的反向HTTP代理伺服器,也可能是你的前端代理伺服器(例如nginx,traefik,apache等),

Rendora 是我見過的接近於完美的動態渲染器,提供零配置伺服器端渲染

我們到底選擇哪一種服務端渲染呢?

Rendora,新的方式非常厲害,有很多優勢:

  1. 方便遷移老的專案,前端和後端程式碼不需要更改。
  2. 可能更快的效能,資源(CPU)消耗可能更少,Golang編寫的二進位制檔案
  3. 多種快取策略
  4. 已經擁有 docker 容器方案

此工具,服務端渲染的頁面需要快取,快取引發的小問題就是

  1. 通過快取解決,效能問題和呼叫API兩次的問題,服務端渲染,客戶端展示渲染,平常呼叫一次API,現在呼叫了兩次。
  2. 被快取的頁面,不能及時清理,比如網站發現使用者發了不良資訊,需要清理,就需要清理快取頁面了。
  3. 如果想提高使用者體驗,瀏覽器端一些頁面需要服務端渲染,這個時候服務端需要請求API,就會有許可權問題,或者直接從快取裡面讀取的HTML,到瀏覽器客戶端,可能會有服務端和瀏覽器端渲染不一致的錯誤。

如果上面兩種方式不在你的考慮範疇之內,那Rendora將是你完美的服務端渲染解決方案

總結

感覺我的輪子 kkt-ssr 好像白寫了一樣,經過分析發現目前還有一點作用吧,至少解決了不多呼叫一次API,和API呼叫許可權問題導致渲染不一致的問題。但是我更推薦Rendora的方式,這將是未來。

不管怎樣,輪子還需要Star的。?

相關文章