性能優化手段之如何從10多秒到3.5秒(fast 3g disable cache)

1.性能優化手段有哪些?

image.png

2.咱們利用這些手段具體作了些什麼?

網絡環境默認爲fast 3g disable cachehtml

構建優化

1.採用同構渲染(服務端渲染+客戶端渲染)

a.什麼是同構渲染,服務端渲染和客戶端渲染

服務端渲染(Server Side Render),其實很是好理解,就是服務器返回一堆html字符串,而後讓瀏覽器顯示。與服務端渲染相對的是客戶端渲染(Client Side Render)。前端

客戶端渲染(Client Side Render):在瀏覽器中經過JS直接進行頁面的渲染路由跳轉等操做。好比:建立一個新的React項目,用腳手架生成項目,而後run起來。 這裏你能夠看到React腳手架自動生成的首頁。打開頁面源代碼
image.pnghtml5

body中除了兼容處理的noscript標籤以外,只有一個id爲root的標籤。那首頁的內容是從哪來的呢?很明顯,是下面的script中拉取的JS代碼控制的。所以,CSR和SSR最大的區別在於前者的頁面渲染是JS負責進行的,然後者是服務器端直接返回HTML讓瀏覽器直接渲染。node

同構渲染:先後端共用一套JS代碼,採用不一樣的構建方式。經過Node服務器進行頁面的首屏生成。webpack

SSR和CSR的渲染流程圖:
image.pnggit

同構渲染的渲染流程圖:
image.pngweb

b.他們的優缺點分別是什麼?

SSR:npm

優勢:後端

1.優秀的SEO瀏覽器

2.首屏加載快

缺點:

1.負載大:因爲渲染任務都交由服務端進行,在高併發的狀況下,對於服務端負載壓力大。
2.複用性能差:由於返回的是整個頁面,對於每一個路由都要從新進行頁面刷新,複用性能 上不友好。
3.先後端耦合嚴重,前端開發依賴於後端,開發形式上不友好。

傳統CSR:

優勢:
1.節省服務器性能。
2.局部刷新,無需每次都請求完整頁面,體驗更好。
3.先後端分離開發。

缺點:

1.因爲頁面顯示過程要進行JS文件拉取和React代碼執行,首屏加載時間會比較慢。

2.對於SEO(Search Engine Optimazition,即搜索引擎優化),徹底無能爲力,由於搜索引擎爬蟲只認識html結構的內容,而不能識別JS代碼內容。

同構渲染:

優勢:兼顧前端渲染的大部分優勢和後端渲染SEO和首屏加載的優勢

缺點:1.須要額外的開發構建成本 2.對服務器有必定負載

c.使用以後效果如何?

CSR的效果

image.png

同構渲染的效果

image.png

經過對比,同構渲染 在下載html文件時,耗費的時間會多出(800ms-580ms)220ms的樣子(由於文檔內容較多的緣由)

CSR的白屏時間爲3.8s

同構渲染的白屏時間爲0.9s

可是,同構渲染在加載html文件的時間就幾乎等於白屏時間,而CSR加載完html文件的時間遠小於它的白屏時間。故咱們能夠看出,同構渲染渲染大大減小了咱們頁面的白屏時間,同時也減小了首屏時間。

d.具體在項目中的使用

由於咱們項目原本是CSR的,若是所有改爲SSR,那麼成本會很大,並且咱們的初衷只是提升性能,並非必定要用SSR,因此咱們就結合了一下,使用了同構渲染。即在服務器端執行一次,用於實現服務器端渲染(首屏直出),在客戶端再執行一次,用於接管頁面交互,獲取須要的對應的數據,核心解決首屏渲染慢的問題。到這裏你們必定會有疑問:

Q1:爲何不在服務端經過請求接口的形式,把全部信息都拿到,這樣就不用走一遍前端渲染了?

A1:由於咱們的項目須要在微信中打開,而後經過微信受權的形式,拿到對應的用戶信息,而後再根據用戶的信息發出請求以及對頁面展現效果做出調整。因此在前期服務端渲染時,拿不到全部的信息,須要經過同構渲染的方式才能完成整個頁面的渲染。

Q2:服務端渲染完了,前端再渲染一次,這樣會消耗性能或者影響展現效果嗎?

A2:不會,前端渲染會去作比較,只會渲染須要改變的DOM,而不會去改變其餘的DOM。

2.按需加載

在優化手段的圖中,構建優化這一塊,除了咱們使用同構渲染,其餘的中心思想都是在講,如何作到按需加載,下面咱們就這一塊具體來說一講。

1.首先咱們須要肯定的就是咱們首屏中有哪些資源是必需的,哪些資源是非必需。js都是要作到異步加載的,同時根據狀況調整成延遲加載和延遲執行的。

2.其次是給咱們首屏中的那些必需的資源,排一個加載順序,作到儘可能不影響咱們的頁面展現,影響展現的就延遲加載或者延遲執行。

a.js的異步加載,延遲加載,延遲執行

先解釋標題,異步加載,延遲執行這2點是能夠經過script標籤加defer屬性來作到,目的是不阻塞渲染,而延遲加載須要視業務場景來調整js文件的位置,目的是減小前期http併發請求數,減小首屏時間。

1.說說什麼是defer,async,以及defer和async的區別是什麼

defer 和 async 是 script 標籤的兩個屬性。

對於defer,加載後續文檔元素的過程將和 此js 的加載並行進行(異步),可是 js 的執行要在全部元素解析完成以後,DOMContentLoaded 事件觸發以前完成。不過defer會按照本來的js的順序執行,因此若是先後有依賴關係的js能夠放心使用。(總結一下就是異步加載,延遲執行)

對於async,這個是html5中新增的屬性,它的做用是可以異步的加載和執行腳本,不由於加載腳本而阻塞頁面的加載,一旦加載到就會馬上執行。在有async的狀況下,js一旦下載好了就會執行,因此頗有可能不是按照本來的順序來執行的。若是js先後有依賴性,用async,就頗有可能出錯。

沒有 defer 或 async,瀏覽器會當即加載並執行指定的腳本,「當即」指的是在渲染該 script 標籤之下的文檔元素以前,也就是說不等待後續載入的文檔元素,讀到就加載並執行。

二者的區別:

相同點:a.不會阻塞頁面渲染 b.對於inline的script(內聯腳本)無效 c.有腳本的onload的事件回調

不一樣點:a.html的版本html4.0中定義了defer;html5.0中定義了async b.defer 執行要在全部元素解析完成以後,DOMContentLoaded 事件觸發以前完成,而每個有async屬性的腳本都在它下載結束以後馬上執行,同時會在window的load事件以前執行。因此就有可能出現腳本執行順序被打亂的狀況。

2.具體在這個項目中的使用場景

七魚客服的SDK 和 微信的SDK,都屬於咱們剛剛說的,按需加載的第二點,這2個js都屬於首屏中須要的文件,可是卻須要延遲加載或者異步加載延遲執行的js。

其中七魚客服的SDK能夠延遲加載,延遲執行的,由於通常狀況用戶一進來頁面是不會去當即點擊諮詢的,因此會給這個script加上defer屬性,作到延遲執行,同時,在諮詢按鈕所在的footer組件中,走到componentDidMount生命週期時纔去加載七魚客服的SDK,就能夠作到不阻塞渲染,減小前期http併發請求數,減小首屏時間。

其次,微信的SDK也是屬於能夠延遲加載,延遲執行的。咱們的項目是在微信中打開的,在項目中咱們須要先加載了微信的SDK,而後設置了微信分享的相關配置,才能點擊分享。由於通常用戶進來也不會當即去點擊分享,因此會放到微信受權成功以後,再去加載微信的SDK,再經過script 標籤上的onload回調函數,去設置微信分享的相關配置,同時給它加上defer屬性,這樣就作到了延遲加載,而且延遲執行。

對比調整先後的performance圖

微信SDK調整前:
image.png

微信SDK調整後:
image.png

能夠看到 調整後微信SDK的加載幾乎對首屏加載沒有較大的影響了。

b.webpack打包策略

默認的分包策略爲:

1新的 chunk 是否被共享或者是來自 node_modules 的模塊

2.新的 chunk 體積在壓縮以前是否大於 30kb

3.按需加載 chunk 的併發請求數量小於等於 5 個

4.頁面初始加載時的併發請求數量小於等於 3 個。

推薦閱讀 https://juejin.im/entry/5b784... 這裏是對webpack分包策略的分析。

總結性地來說,webpack分包是一個博弈的過程,須要結合具體的業務場景來決定是否分包。可是在咱們作性能優化的時候,有些基本點能夠注意:

1.一些很小的包 好比只有幾kb,可是由圖能夠看出
image.png

這個包絕大部分時間都花在了創建鏈接上,而它實際只有1.7kb.這樣就能夠考慮不拆這個包,將這個包和其餘資源合併。

2.一些很大的包(具體怎麼衡量包的大小,參考webpack默認的30kb)視它阻塞渲染的程度考慮是否拆包。

3.對打包的文件,要儘可能壓縮,減小其大小。

對於靜態資源的優化

1.圖片資源的優化

a.對圖片作壓縮,在項目中對圖片大小的要求是:1.gif不超過1M 2.其他不超過200kb3.寬度最多爲頁面寬度三倍。
b.兼容性的寫法:經過<picture>元素使用在不一樣情景下使用不一樣格式的圖片,優先級依次爲webp,漸進式jpeg, png。

首先是對picture標籤的介紹:HTML <picture> 元素經過包含零或多個 <source> 元素和一個 <img> 元素來爲不一樣的顯示/設備場景提供圖像版本。瀏覽器會選擇最匹配的子 <source> 元素,若是沒有匹配的,就選擇 <img> 元素的 src 屬性中的URL。而後,所選圖像呈如今<img>元素佔據的空間中。

eg:
image.png

oss 就支持轉 webp, 只須要在圖片連接後面加上?x-oss-process=image/format,webp 就能夠了,不須要本身手動去轉,iOS不支持webp,因此會在iOS設備上使用漸進式jpeg,對應的漸進式jpeg圖片的說明 (confluence文檔地址使用漸進式JPEG來提高用戶體驗),對於須要使用到透明度的圖片才推薦使用png,不然不推薦使用png格式的圖片。

c.對非首屏圖片(img 背景圖 視頻的預覽圖)作懶加載。對於首屏的圖片作懶加載反而會增長首屏時間。懶加載的npm包地址 https://gitlab.xiguacity.cn/e...

2.使用CDN

將咱們打包的靜態資源文件上傳到阿里雲上。

其餘優化手段

1.http/2

http/2這一塊,因爲不是由前端去設置,可是須要你們對它有所瞭解。

a.http/2是什麼?
HTTP/2(超文本傳輸協議第2版,最初命名爲HTTP 2.0),簡稱爲h2或h2c,是HTTP協議的的第二個主要版本。

b.http/2和http/1.X相比有什麼優點?
a.新的二進制格式(Binary Format),HTTP1.x的解析是基於文本。基於文本協議的格式解析存在自然缺陷,文本的表現形式有多樣性,要作到健壯性考慮的場景必然不少,二進制則不一樣,只認0和1的組合。基於這種考慮HTTP2.0的協議解析決定採用二進制格式,實現方便且健壯。

b.多路複用(MultiPlexing),即鏈接共享,即每個request都是是用做鏈接共享機制的。一個request對應一個id,這樣一個鏈接上能夠有多個request,每一個鏈接的request能夠隨機的混雜在一塊兒,接收方能夠根據request的 id將request再歸屬到各自不一樣的服務端請求裏面。

c.header壓縮,如上文中所言,對前面提到過HTTP1.x的header帶有大量信息,並且每次都要重複發送,HTTP2.0使用encoder來減小須要傳輸的header大小,通信雙方各自cache一份header fields表,既避免了重複header的傳輸,又減少了須要傳輸的大小。

d.服務端推送(server push),同SPDY同樣,HTTP2.0也具備server push功能。

2.server workers

a.server wokers是什麼?
service worker 是獨立於當前頁面的一段運行在瀏覽器後臺進程裏的腳本。

service worker不須要用戶打開 web 頁面,也不須要其餘交互,異步地運行在一個徹底獨立的上下文環境,不會對主線程形成阻塞。基於service worker能夠實現消息推送,靜默更新以及地理圍欄等服務。

b.它能解決什麼問題?
Service Worker 可使你的應用先訪問本地緩存資源,因此在離線狀態時,在沒有經過網絡接收到更多的數據前,仍能夠提供基本的功能監控。

咱們在作頁面性能優化時,也考慮過使用server workers,通常server works是在第二次訪問時能訪問到已有的本地緩存資源,咱們的項目的用戶通常只會訪問一次,因此咱們項目中沒有使用這個方法,只是介紹給你們之後解決問題能夠多一種思路。

3.結語

以上就是咱們在優化項目中所用到的性能優化手段,其中存在有不少能夠改進和調整的地方,也歡迎你們都提出來。在性能優化這一塊咱們也會持續地去作,在作的同時沉澱下來的文檔,也但願對你們之後在對本身項目進行性能優化的時候能有所幫助。

相關文章
相關標籤/搜索