React 官網為什麼那麼快?

語言: CN / TW / HK
ead>

攜手創作,共同成長!這是我參與「掘金日新計劃 · 8 月更文挑戰」的第1天,點選檢視活動詳情

當我們開啟 React 官網時,會發現從瀏覽器上輸入url 到頁面首屏完全展示這一過程所花的時間極其短暫,而且在點選頁面中的連結切換路由時非常順滑,幾乎頁面可以做到“秒切”的效果,根本不會出現卡頓等待的情況,於是帶著敬畏之心對“react到底是怎麼做到的”的問題開始了本次探索,發現其主要有以下的優化手段

服務端 SSR 渲染

下面是react官方中文文件首頁的截圖,大家注意下方的紅色區域,後面會作為推斷的一個理由

當我們開啟控制檯之後,點選network並選擇 DOC文件請求,就會發現有一個請求路徑為https://react.docschina.org/GET請求,響應結果為一個 html文件,裡面剛好能找到對應上圖中紅色區域文字的文字,這也就佐證了這個html文件所對應的頁面就是react官網首頁,而這種渲染頁面的方式就稱之為服務端 SSR渲染

很多人會將客戶端渲染 CSR與 服務端渲染 SSR弄混,下面我們簡單介紹一下它們各自的特點,看完之後相信你就能夠了解他們的區別了

頁面的渲染流程

在開始之前,我們先來回顧一下頁面最基本的渲染流程是怎麼樣的?

  • 瀏覽器通過請求得到一個 HTML文字
  • 渲染程序解析 HTML 文字,構建 DOM
  • 瀏覽器解析 HTML 的同時,如果遇到內聯樣式或者樣本樣式,則下載並構建樣式規則(stytle rules)。若遇到 Javascript 指令碼,則會下載並執行指令碼
  • DOM 樹和樣式規則構建完成之後,渲染程序將兩者合併成渲染樹(render tree
  • 渲染程序開始對渲染樹進行佈局,生成佈局樹(layout tree
  • 渲染程序對佈局樹進行繪製,生成繪製記錄
  • 渲染程序對佈局樹進行分層,分別柵格化每一層並得到合成幀
  • 渲染程序將合成幀傳送給 GPU 程序將影象繪製到頁面中

可以看到,頁面的渲染其實就是瀏覽器將HTML文字轉化為頁面幀的過程

客戶端渲染 CSR

而如今我們大部分 WEB 應用都是使用 JavaScript 框架(VueReactAngular)進行頁面渲染的,也就是說,在執行 JavaScript 指令碼之前,HTML 頁面已經開始解析並且構建 DOM 樹了,JavaScript 指令碼只是動態的改變 DOM 樹的結構,使得頁面成為希望成為的樣子,這種渲染方式叫動態渲染,也可以叫客戶端渲染 CSRclient side render

下面程式碼為瀏覽器請求 react 編寫的網頁時響應回的程式碼,返回的 HTML 其實只是一個空殼,裡面並沒有具體的文字內容,需要執行 JavaScript 指令碼之後才會渲染我們真正想要的頁面

```html

Jira任務管理系統

```

服務端渲染 SSR

顧名思義,服務端渲染就是在瀏覽器請求頁面 URL 的時候,服務端將我們需要的 HTML 文字組裝好,並返回給瀏覽器,這個 HTML 文字被瀏覽器解析之後,不需要經過 JavaScript 指令碼的執行,即可直接構建出希望的 DOM 樹並展示到頁面中。這個服務端組裝HTML的過程,叫做服務端渲染

下面是服務端渲染時返回的 HTML 文件,由於程式碼量實在是太多,所以只保留了有象徵意義的部分程式碼,但不難發現,服務端渲染返回的 HTML 文件中是具有頁面中的核心文字的

```html


一次學習,跨平臺編寫

無論你現在使用什麼技術棧,在無需重寫現有程式碼的前提下,通過引入 React 來開發新功能。

React 還可以使用 Node 進行伺服器渲染,或使用 React Native 開發原生移動應用。

```

現在我們就可以回答為什麼react官網要使用服務端渲染了?

因為相對於客戶端渲染,服務端渲染在瀏覽器請求URL之後已經得到了一個帶有資料的HTML文字,瀏覽器只需要解析HTML,直接構建DOM樹就可以。而客戶端渲染,需要先得到一個空的HTML頁面,這個時候頁面已經進入白屏,之後還需要經過載入並執行 JavaScript、請求後端伺服器獲取資料、JavaScript 渲染頁面幾個過程才可以看到最後的頁面。特別是在複雜應用中,由於需要載入 JavaScript指令碼,越是複雜的應用,需要載入的 JavaScript指令碼就越多、越大,這會導致應用的首屏載入時間非常長,從而降低了體驗感

總結

無論是服務端渲染還是客戶端渲染,一開始都是要請求一個 HTML 文字,但是區別就在於這個文字是否已經被服務端組裝好了

  • 客戶端渲染還需要去下載和執行Javascript指令碼之後才能得到我們想要的頁面效果,所以速度會比服務端渲染慢很多
  • 服務端渲染得到的HTML文件就已經組合好了對應的文字,瀏覽器請求到之後直接解析渲染出來即可,不需要再去下載和執行額外的Javasript 指令碼,所以速度會比客戶端渲染快很多

下圖是客戶端渲染和服務端渲染的流程圖:

一些預載入/預處理資源的方式

研究完首屏渲染之後,我們再來研究一下路由跳轉後內容的切換。經常看 react 文件的朋友可能早就發現了,其路由跳轉無比絲滑,感覺就像是一個靜態頁面一樣,完全沒有傳送網路請求的痕跡,比如我現在處在hook 簡介這一個板塊,當我點選 hook 規則 目錄之後

發現頁面瞬間秒切了過去,內容也瞬間展現在了出來,沒有一絲卡頓,使用者體驗直接爆炸,這到底是怎麼做到的呢?

下面我們就來一點一點分析它的每個優化手段

preload

在當前頁面中,你可以指定可能或很快就需要的資源在其頁面生命週期的早期——瀏覽器的主渲染機制介入前就進行預載入,這可以讓對應的資源更早的得到載入並使用,也更不易阻塞頁面的初步渲染,進而提升效能

關鍵字 preload 作為元素 <link> 的屬性 rel的值,表示使用者十分有可能需要在當前瀏覽中載入目標資源,所以瀏覽器必須預先獲取和快取對應資源 。下面我們來看一個示例:

<link as="script" rel="preload" href="/webpack-runtime-732352b70a6d0733ac95.js">

這樣做的好處就是讓在當前頁面中可能被訪問到的資源提前載入但並不阻塞頁面的初步渲染,進而提升效能

下面是 react文件中對 preload關鍵字的使用,告訴瀏覽器等等可能需要這個資源,希望能夠儘早下載下來

可以預載入的資源有很多,現在瀏覽器支援的主要有: