1. 程式人生 > >前後端渲染和同構渲染

前後端渲染和同構渲染

我為什麼要選這篇文章呢?

十年前,幾乎所有網站都使用 ASP、Java、PHP 這類做後端渲染,但後來隨著 jQuery、Angular、React、Vue 等 JS 框架的崛起,開始轉向了前端渲染。從 2014 年起又開始流行了同構渲染,號稱是未來,集成了前後端渲染的優點,但轉眼間三年過去了,很多當時壯心滿滿的框架(Rendlr、Lazo)從先驅變成了先烈。同構到底是不是未來?自己的專案該如何選型?我想不應該只停留在追求熱門和拘泥於固定模式上,忽略了前後端渲染之“爭”的“核心點”,關注如何提升“使用者體驗”。

這篇文章分析了前端渲染的優勢,並沒有進行深入探討。我想通過它為切入口來深入探討一下。

明確三個概念:「後端渲染」指傳統的 ASP、Java 或 PHP 的渲染機制;「前端渲染」指使用 JS 來渲染頁面大部分內容,代表是現在流行的 SPA 單頁面應用;「同構渲染」指前後端共用 JS,首次渲染時使用 Node.js 來直出 HTML。一般來說同構渲染是介於前後端中的共有部分。

2. 內容概要

前端渲染的優勢:
  1. 區域性重新整理。無需每次都進行完整頁面請求
  2. 懶載入。如在頁面初始時只加載可視區域內的資料,滾動後rp載入其它資料,可以通過react-lazyload 實現
  3. 富互動。使用 JS 實現各種酷炫效果
  4. 節約伺服器成本。省電省錢,JS 支援 CDN 部署,且部署極其簡單,只需要伺服器支援靜態檔案即可
  5. 天生的關注分離設計。伺服器來訪問資料庫提供介面,JS 只關注資料獲取和展現
  6. JS 一次學習,到處使用。可以用來開發 Web、Serve、Mobile、Desktop 型別的應用
後端渲染的優勢:
  1. 服務端渲染不需要先下載一堆 js 和 css 後才能看到頁面(首屏效能)
  2. SEO
  3. 服務端渲染不用關心瀏覽器相容性問題(隨意瀏覽器發展,這個優點逐漸消失)
  4. 對於電量不給力的手機或平板,減少在客戶端的電量消耗很重要

以上服務端優勢其實只有首屏效能和 SEO 兩點比較突出。但現在這兩點也慢慢變得微不足道了。React 這類支援同構的框架已經能解決這個問題,尤其是 Next.js 讓同構開發變得非常容易。還有靜態站點的渲染,但這類應用本身複雜度低,很多前端框架已經能完全囊括。

3. 精讀

本次提出獨到觀點的同學有:@流形@黃子毅@camsongTurbe Xue@楊森@淡蒼@留影@FrankFang@alcat2008@javie007@xile611@twobin 精讀由此歸納。

大家對前端和後端渲染的現狀基本達成共識。即前端渲染是未來趨勢,但前端渲染遇到了首屏效能和SEO的問題。對於同構爭議最多。在此我歸納一下。


前端渲染遇到的問題


前端渲染主要面臨的問題有兩個 SEO、首屏效能

SEO 很好理解。由於傳統的搜尋引擎只會從 HTML 中抓取資料,導致前端渲染的頁面無法被抓取。前端渲染常使用的 SPA 會把所有 JS 整體打包,無法忽視的問題就是檔案太大,導致渲染前等待很長時間。特別是網速差的時候,讓使用者等待白屏結束並非一個很好的體驗。

同構的優點

同構恰恰就是為了解決前端渲染遇到的問題才產生的,至 2014 年底伴隨著 React 的崛起而被認為是前端框架應具備的一大殺器,以至於當時很多人為了用此特性而 放棄 Angular 1 而轉向 React。然而近3年過去了,很多產品逐漸從全棧同構的理想化逐漸轉到首屏或部分同構。讓我們再一次思考同構的優點真是優點嗎?

1. 有助於 SEO
  • 首先確定你的應用是否都要做 SEO,如果是一個後臺應用,那麼只要首頁做一些靜態內容宣導就可以了。如果是內容型的網站,那麼可以考慮專門做一些頁面給搜尋引擎
  • 時到今日,谷歌已經能夠可以在爬蟲中執行 JS 像瀏覽器一樣理解網頁內容,只需要往常一樣使用 JS 和 CSS 即可。並且儘量使用新規範,使用 pushstate 來替代以前的 hashstate。不同的搜尋引擎的爬蟲還不一樣,要做一些配置的工作,而且可能要經常關注資料,有波動那麼可能就需要更新。第二是該做 sitemap 的還得做。相信未來即使是純前端渲染的頁面,爬蟲也能很好的解析。
2. 共用前端程式碼,節省開發時間
其實同構並沒有節省前端的開發量,只是把一部分前端程式碼拿到服務端執行。而且為了同構還要處處相容 Node.js 不同的執行環境。有額外成本,這也是後面會具體談到的。

3. 提高首屏效能
由於 SPA 打包生成的 JS 往往都比較大,會導致頁面載入後花費很長的時間來解析,也就造成了白屏問題。服務端渲染可以預先使到資料並渲染成最終 HTML 直接展示,理想情況下能避免白屏問題。在我參考過的一些產品中,很多頁面需要獲取十幾個介面的資料,單是資料獲取的時候都會花費數秒鐘,這樣全部使用同構反而會變慢。

同構並沒有想像中那麼美

1. 效能
把原來放在幾百萬瀏覽器端的工作拿過來給你幾臺伺服器做,這還是花挺多計算力的。尤其是涉及到圖表類需要大量計算的場景。這方面調優,可以參考walmart的調優策略

個性化的快取是遇到的另外一個問題。可以把每個使用者個性化資訊快取到瀏覽器,這是一個天生的分散式快取系統。我們有個資料類應用通過在瀏覽器合理設定快取,雙十一當天節省了 70% 的請求量。試想如果這些快取全部放到伺服器儲存,需要的儲存空間和計算都是很非常大。

2. 不容忽視的伺服器端和瀏覽器環境差異
前端程式碼在編寫時並沒有過多的考慮後端渲染的情景,因此各種 BOM 物件和 DOM API 都是拿來即用。這從客觀層面也增加了同構渲染的難度。我們主要遇到了以下幾個問題:
  • document 等物件找不到的問題
  • DOM 計算報錯的問題
  • 前端渲染和服務端渲染內容不一致的問題
由於前端程式碼使用的 window 在 node 環境是不存在的,所以要 mock window,其中最重要的是 cookie,userAgent,location。但是由於每個使用者訪問時是不一樣的 window,那麼就意味著你得每次都更新 window。
而服務端由於 js require 的 cache 機制,造成前端程式碼除了具體渲染部分都只會載入一遍。這時候 window 就得不到更新了。所以要引入一個合適的更新機制,比如把讀取改成每次用的時候再讀取。
export const isSsr = () => (
  !(typeof window !== 'undefined' && window.document && window.document.createElement && window.setTimeout)
);
原因是很多 DOM 計算在 SSR 的時候是無法進行的,涉及到 DOM 計算的的內容不可能做到 SSR 和 CSR 完全一致,這種不一致可能會帶來頁面的閃動。

3. 記憶體溢位
前端程式碼由於瀏覽器環境重新整理一遍記憶體重置的天然優勢,對記憶體溢位的風險並沒有考慮充分。
比如在 React 的 `componentWillMount` 裡做繫結事件就會發生記憶體溢位,因為 React 的設計是後端渲染只會執行 `componentDidMount` 之前的操作,而不會執行 `componentWillUnmount` 方法(一般解綁事件在這裡)。

4. 非同步操作
前端可以做非常複雜的請求合併和延遲處理,但為了同構,所有這些請求都在預先拿到結果才會渲染。而往往這些請求是有很多依賴條件的,很難調和。純 React 的方式會把這些資料以埋點的方式打到頁面上,前端不再發請求,但仍然再渲染一遍來比對資料。造成的結果是流程複雜,大規模使用成本高。幸運的是 Next.js 解決了這一些,後面會談到。

5. simple store(redux)
這個 store 是必須以字串形式塞到前端,所以複雜型別是無法轉義成字串的,比如function。

總的來說,同構渲染實施難度大,不夠優雅,無論在前端還是服務端,都需要額外改造。

首屏優化

再回到前端渲染遇到首屏渲染問題,除了同構就沒有其它解法了嗎?總結以下可以通過以下三步解決


1. 分拆打包
現在流行的路由庫如 react-router 對分拆打包都有很好的支援。可以按照頁面對包進行分拆,並在頁面切換時加上一些 loading 和 transition 效果。

2. 互動優化
首次渲染的問題可以用更好的互動來解決,先看下 linkedin 的渲染

有什麼感受,非常自然,開啟渲染並沒有白屏,有兩段載入動畫,第一段像是載入資源,第二段是一個載入佔位器,過去我們會用 loading 效果,但過渡性不好。近年流行 Skeleton Screen 效果。其實就是在白屏無法避免的時候,為了解決等待載入過程中白屏或者介面閃爍造成的割裂感帶來的解決方案。

3. 部分同構
部分同構可以降低成功同時利用同構的優點,如把核心的部分如選單通過同構的方式優先渲染出來。我們現在的做法就是使用同構把選單和頁面骨架渲染出來。給使用者提示資訊,減少無端的等待時間。

相信有了以上三步之後,首屏問題已經能有很大改觀。相對來說體驗提升和同構不分伯仲,而且相對來說對原來架構破壞性小,入侵性小。是我比較推崇的方案。

總結

我們贊成客戶端渲染是未來的主要方向,服務端則會專注於在資料和業務處理上的優勢。但由於日趨複雜的軟硬體環境和使用者體驗更高的追求,也不能只拘泥於完全的客戶端渲染。同構渲染看似美好,但以目前的發展程度來看,在大型專案中還不具有足夠的應用價值,但不妨礙部分使用來優化首屏效能。做同構之前 ,一定要考慮到瀏覽器和伺服器的環境差異,站在更高層面考慮。

相關推薦

前後渲染渲染

我為什麼要選這篇文章呢?十年前,幾乎所有網站都使用 ASP、Java、PHP 這類做後端渲染,但後來隨著 jQuery、Angular、React、Vue 等 JS 框架的崛起,開始轉向了前端渲染。從 2014 年起又開始流行了同構渲染,號稱是未來,集成了前後端渲染的優點,但轉眼間三年過去了,很多當時壯心滿

無痛學會各種 2 的 Vue2+Vuex2+Webpack2 前後渲染

感謝有人看我扯技術,這篇文章主要介紹最近非常火的vue2前端框架的特點和vue2+vuex2+webpack2各種2的前後端同構渲染架構搭建流程,最後會附上程式碼,文章想到啥寫啥,如果存在錯誤,或者大家有什麼意見建議,歡迎大家指出來 Vue2 和 Vue1 的對比 v

客戶渲染伺服器短渲染

舉例說明: 1.客戶端渲染 客戶端渲染:說的應該是剛進入頁面時,商品列表這些資料都不給你,不會渲染出這些資料。然後載入script時,再用ajax或者fetch之類的發起了請求另一個介面,服務端返回了商品列表的json資料給你,你在js中用模板引擎之類的技術,把這些資料拼成html字

前後分離 ajax域重定向跨域重定向

前提:前端控制頁面跳轉,後端只提供介面,返回json格式資料,因此前端請求均是ajax請求 同域 伺服器端重定向:response.sendRedirect(url) ajax請求接收到狀態碼:302,同時response header 中增加Location欄位,瀏覽器會自動重定向

好程式設計師web前端分享什麼是前端渲染

  好程式設計師web前端分享什麼是前端同構渲染,同構渲染指的是前後端都使用了js,首次渲染的時候使用nodejs載入了我們的HT

瀏覽器渲染服務器渲染區別

component 能夠 開發效率 這也 體驗 nginx代理 服務器 osc 插入 1、為什麽會有服務器渲染與客戶端渲染?   越來越復雜的 UI 意味著越來越重的渲染工作。目前通常有兩種選擇:服務器渲染與客戶端渲染。   以 Jade, YAML 為代表的模板渲染引擎一

vue釋出中的前後分離前後不分離

前後端分離 思路:前端和後臺完全分離.前端提供靜態的css和js,在執行時將css和js給後端,後端進行資料的請求(ajax) 前後端分離就是前端和後臺在不同的伺服器上。基本是前端一個nginx加css和js 後端nginx加index.html 當用戶訪問的時候,訪問後端nginx的網址,執行後端的in

ArcEngine10.2設計與開發課程學習(作業四)——實現地圖的簡單渲染唯一值渲染

所有習題材料:連結:HTTPS://pan.baidu.com/s/1oiylGi6IEgndYO2j9_oQnQ  提取碼:jp3r  複製這段內容後開啟百度網盤手機應用程式,操作更方便哦 本題EXE:連結:HTTPS://pan.baidu.com/s/10_buC4K1

Vue+Koa2移動電商實戰 (十一)前後通訊跨域處理

今天學習的是前後端的通訊和後端跨域的處理 首先安裝koa-bodyparser中介軟體到我們專案中來,以便我們後端接收前端傳送過來的請求 npm install --save koa-bodyparser 安裝完成後在service/index.js中引入 const bodyPars

前後聯調真機測試以及上線

前後端聯調很簡單:只要修改config/index.js的內容就可以了 這裡要求你的資料在伺服器端的/api資料夾下面。就可以了。 如果伺服器在不在本地怎麼辦呢 就不能寫localhost了,而是域名,或者ip 前端請求就可以轉發給任何一臺伺服器了.,從而非常

聊一聊web開發的前後分離頁碼分離

我一直對web非常感興趣,在這個APP為主導的時代,我依然覺得未來的社會是屬於瀏覽器的。 不過今天不說瀏覽器,說說web中的前後端分離和頁碼分離,可能題目看起來怪怪的,因為【前後端分離】和【頁碼分離】看上去是一個概念。 實際上,前後端分離指的是後端程式碼和前端程式碼的分離,

React前後如何,防止重復渲染

linux首先解釋React前後端同構、React首屏渲染的概念。然後通過這2個概念解決服務端渲染完成後瀏覽器端重復渲染的問題。什麽叫前後端同構?為了解決某些問題(比如SEO、提升渲染速度等)react 提供了2個方法在服務端生成一個HTML文本格式的字符串。在得到了這個HTML格式的字符串之後,通常會將其組

淺談React前後防止重複渲染

什麼叫前後端同構? 為了解決某些問題(比如SEO、提升渲染速度等)react 提供了2個方法在服務端生成一個HTML文字格式的字串。在得到了這個HTML格式的字串之後,通常會將其組裝成一個頁面直接返回給使用者的瀏覽器。 到這裡,服務端的活已經幹完了,然後就是瀏覽器這邊幹活

服務渲染客戶渲染的對比

這裡結合art-template模板引擎說明。 首先了解下前端頁面中如何使用art-template 1、script 標籤匯入包,當這個標籤匯入完畢後,在window全域性中就有了template 函式。 2、建立一個script標籤,內部是模板字串 <script type="te

node——10-服務渲染客戶渲染的區別

客戶端渲染不利於 SEO 搜尋引擎優化 服務端渲染是可以被爬蟲抓取到的,客戶端非同步渲染是很難被爬蟲抓取到的 所以你會發現真正的網站既不是純非同步也不是純服務端渲染出來的 而是兩者結合來做的 例如京東商品列表是採用的服務端渲染,目的是為了 SEO 搜尋引擎優化 而它的商品評論列表

前端路由路由,前端渲染渲染

1.vue-router和koa-router的區別 vue-router是前端路由,koa-router是後端路由。 前端路由 定義:在單頁面應用,大部分頁面結構不變,只改變部分內容的使用 優點:使用者體驗好,不需要每次都從伺服器全部獲取,快速展現給使用者 缺點: 使用瀏覽器的

從壹開始前後分離 [ Vue2.0+.NetCore2.1] 二十六║Client渲染、Server渲染知多少{補充}

前言 書接上文,昨天簡單的說到了 SSR 服務端渲染的相關內容《二十五║初探SSR服務端渲染》,主要說明了相關概念,以及為什麼使用等,昨天的一個小栗子因為時間問題,沒有好好的給大家鋪開來講,今天呢,咱們就繼續說一下這個 SSR 服務端渲染,並結合著 Client 客戶端渲染,一起說一說相關的內容,當然還是圍

從壹開始前後分離 [ vue + .netcore 補充教程 ] 二九║ Nuxt實戰:非同步實現資料雙渲染

回顧 哈嘍大家好!又是元氣滿滿的周~~~二哈哈,不知道大家中秋節過的如何,馬上又是國慶節了,博主我將通過三天的時間,給大家把專案二的資料添上(這裡強調下,填充資料不是最重要的,最重要的是要配合著讓大家明白 nuxt.js 是如何一步步實現服務端渲染的),雖說是基於 Nuxt 的,但是資料來源還是我們的老

從壹開始前後分離 [ vue + .netcore 補充教程 ] 三十║ Nuxt實戰:動態路由+

上期回顧 說接上文《二九║ Nuxt實戰:非同步實現資料雙端渲染》,昨天咱們通過專案二的首頁資料處理,簡單瞭解到了 nuxt 非同步資料獲取的作用,以及親身體驗了幾個重要資料夾的意義,整篇文章也一直在往如何實現服務端渲染的方向講解,因為我個人感覺這個是一個重點,如果是隻會如何使用的話,大家就可以走馬觀花的看

react精華之next.js getInitialProps自動切換服務渲染瀏覽器渲染 而不需要同時使用渲染

我們已經知道了伺服器端渲染的原理,你只需要搭建一個 Express 伺服器,在伺服器端手工打造『脫水』,在瀏覽器端做『注水』,完成某個頁面的伺服器端渲染並不難。 不過,伺服器端渲染的問題並不這麼簡單,一個最直接的問題,就是怎麼處理多個頁面的『單頁應用』(Single-Page-Applicati