web頁面渲染(一)

做爲開發者,咱們常常會面臨一些影響咱們整個網站結構的決定,其中web開發者必定要作的核心決定之一就是在應用程序中實現邏輯和渲染的位置。這可能比較難,由於有不少不一樣的方式來構建一個網站。javascript

咱們在這一領域的瞭解主要來源於在過去的幾年在Chrome工做期間,一直與一些大的網站的交流得來的。從廣義上來說,咱們鼓勵開發人員去經過徹底rehydration方法進行服務端渲染或者是靜態渲染。html

爲了更好的理解咱們所選擇的技術架構,咱們須要對每種方法有一種紮實的理解,而且在談論時要使用一致的術語。這些方式的不一樣點有助於咱們說明經過性能和渲染之間尋求一個平衡。java

術語

渲染

SSR: Server-Side Rendering - 在服務器端渲染內容的方式。web

CSR: Client-Side Rendering - 一般在瀏覽器中使用DOM來渲染應用程序的過程。瀏覽器

Rehydration: 在客戶端「啓動」Javascript視圖,使得他們可以重用服務器端渲染的html的dom樹和數據。緩存

Prerendering: 在構建時運行客戶端應用程序來使用其初始狀態做爲靜態的html頁面。服務器

性能

TTFB: Time to First Byte - 點擊一個連接到返回的第一個字節數據所用的時間。網絡

FP: First Paint - 首次任何像素對用戶可見的時間(也就是首先將像素繪製到屏幕的時刻)。架構

FCP: First Contentful Paint - 首次內容對用戶可見的時間(也就是瀏覽器將第一個 DOM 渲染到屏幕的時間)。dom

TTI: Time To Interactive - 頁面變爲可交互的時間。

服務器端渲染

服務器端渲染會在服務器上生成整個的HTML頁面,而後總體返回給瀏覽器。因爲它在返回給瀏覽器以前就已經處理好了,因此會避免客戶端在數據獲取和模板化的額外開銷。

服務器渲染很快就會產生First Paint(FP)和First Contentful Paint(FCP)。在服務器端運行頁面邏輯和渲染,使之避免了所以而發送大量的Javascript給客戶端。也會有助於咱們實現一個快速的Time To Interactive(TTI)。這是可能的,由於在服務器端渲染的話,你僅僅須要發送文本和連接給瀏覽器。這種方式在大範圍的設備和網絡環境下都會很好的運行,與此同時也會提起你對瀏覽器優化的興趣,好比說流文檔解析。

經過服務器端渲染,用戶不太可能等待CPU綁定的javascript處理完畢以後才能去使用您的站點。即便是第三方js不可避免。使用服務器端渲染也會減小你的js開銷,會給您處理其餘事情留有更多的「預算」。然而,這種方式有一個主要的缺點:在服務器端生成頁面會減慢你的Time To First Byte(TTFB)。

服務器端渲染對於你的應用程序是否夠用,很大一部分依賴於你我的的構建經驗。在服務器端渲染和客戶端渲染哪個更好這個爭論曾經持續了很長時間。可是要記住很重要的一點,你能夠在一些頁面中使用服務器端渲染,而不是所有都用。一些網站已經成功使用了混合渲染技術,Netflix在服務器端渲染,呈現其相對於靜態的頁面,同時爲交互繁重的頁面預取js,給這些較重的客戶端頁面提供一個更快的加載機會。

許多現代瀏覽器,類庫和架構使得在客戶端和服務器端渲染同一個應用程序成爲可能。這些技術能夠被用於服務器端渲染,然而,重要的是注意在客戶端和服務器端渲染的架構都有他們不一樣的解決方案,具備很是不一樣的性能特徵和權衡。React用戶可使用renderToString()或者是在其之上的解決方案來實現服務器端渲染,好比說Next.js。Vue用戶能夠查閱Vue的server rendering guide或者是Nuxt。Angular有Universal。最流行的解決方案會採用某些形式的hydration。在選擇一個工具以前要注意使用的方法。

靜態渲染

靜態渲染在構建時發生,會提供一個很快的First Paint,First Contentful Paint, Time To Interactive - 假設客戶端js是有限的。跟服務器端渲染區別之一是它會設法實現一個始終如一的快速的Time To First Byte,由於HTML頁面沒必要動態生成。一般來講,靜態渲染意味着會提早對每個URL生成一個單獨的HTML文件。因爲預先生成了HTML的響應,因此靜態渲染能夠部署在多個CDN來用於邊緣緩存。

靜態渲染的解決方案多種多樣,像Gatsby這樣的工具,開發者會感受他們的應用程序是動態渲染的,而不是做爲構建時生成的。而像Jekly和Metalsmith則會擁抱他們的靜態生態系統,提供更多模板驅動的方法。

靜態渲染的缺點之一就是要爲每個可能的URL單獨生成一個HTML文件,當你不能提早預知這些URL都有什麼,或者網站有很是多的惟一頁面的時候,這或許是一個挑戰,又或者是不可能實現的。

React用戶可能很熟悉Gatsby,Next.js,static export或者是Navi - 他們都使得做者使用組件變得很方便。然而,重要的是理解靜態渲染和預渲染的不一樣點:靜態渲染頁面是可交互的,不須要執行太多的客戶端的js,而預渲染則會提高單頁應用的First Paint或者是First Contentful Paint,爲了讓頁面變爲真正的可交互其必定要在客戶端啓動。

若是你不肯定給定的解決方案是靜態渲染,仍是預渲染,嘗試下以下測試:禁用Javascript,加載已經建立好的頁面。對於靜態渲染頁面,若是不啓用Javascript,大部分功能依然存在。而對於預渲染頁面,可能依然有一些基本的功能可使用,好比說超連接,可是大部分頁面將會是惰性的。

另外一個有用的測試是使用Chrome DevTool下降你的網絡帶寬,觀察頁面變爲可交互以前Javascript已經下載的數量。預渲染一般須要更多的Javascript來使頁面變的可交互,而且Javascript要比靜態渲染使用的漸進加強方法要更復雜。

服務器端渲染 vs 靜態渲染

服務器端渲染並非靈丹妙藥 - 它的動態特性會帶來明顯的計算性能開銷。許多服務器端渲染解決方案都不會提前刷新,可能會致使延遲TTFB或者是發送的數據量加倍。在React中,renderToString()多是很慢的,由於它是同步而且是單線程的。要使得服務器渲染「正確」可能會涉及查找或者構建一個組件緩存的解決方案,管理內存消耗,等等。你一般會屢次處理/從新構建相同的應用程序 - 一次在客戶端,一次在服務器端。僅僅是由於服務器端渲染可使某些東西更快顯示,但並非忽然意味着會減小你的工做量。

服務器端渲染能夠按須要爲每一個URL生成對應的HTML,可是它卻慢於靜態渲染的內容。若是你能夠進行一些額外的工做,那麼服務器端渲染 + HTML緩存能夠極大的減小服務器渲染的時間。服務器端渲染的優勢是有能力獲取更多「實時」的數據而且返回比靜態渲染更加完整的結果集,個性化的頁面是服務器渲染的一個具體的事例,不過這種對於靜態渲染來講,就不太適合了。

在構建PWA的時候,服務器端渲染也能夠提出一些有有趣的決策。因此是全頁server worker更好,仍是用服務器渲染僅僅渲染單獨的內容片斷更好呢?

本文翻譯自:

https://developers.google.com/web/updates/2019/02/rendering-on-the-web

本文轉載自[http://www.lht.ren/article/13/](http://www.lht.ren/article/13/)

相關文章
相關標籤/搜索