前端效能優化的目的在於讓頁面載入的更快,為使用者帶來更好的使用者體驗。那麼前端效能要如何優化呢?具體要怎麼做?以下這篇文章就來帶大家來了解一些關於前端效能優化的知識點。
重複看下以下三個問題。
假如你有,那你的答案在哪。
例如整個天貓首頁。答案有很多種,你看看有木頭有你想的那種。
create-react-app
初始化一個專案吧。首頁寫好一些元件,例如豆腐塊、Header、Bar
、長滾動ScrollView
。然後專案編譯、打包上線。
webpack
手搭一個項目。
路由按需載入弄上,可無痕瀏覽的帶loadmore
的高效能ScrollList
#。
因為是首頁,明顯會牽扯到首畫面載入的問題。那骨架螢幕給安排上吧。
再搞一套webpack的最佳實踐,目的是能最終得到體積盡量小的打包檔案。
SSR來一套吧。因為首頁DOM結構太複雜了,如果走Virtual DOM
那一套,等到GPU渲染UI就太慢了。
以上,有命中你的某個點嗎?不管有木頭有道理,這是你想到的點嗎?是不是總覺得好像少了點什麼?
本篇文章不細講其它內容。但到這了就得提一嘴,留個印象。
- 系統層設計
- 一個新系統留20%來滿足目前已有業務。剩下80% 用來系統演進。可以思考下,天貓首頁一直變,卻仍能保證性能達標。
- 業務層設計
- 已有業務是否與其它業務產生了耦合,是否存在前置業務,如果有那前置業務的權限又在哪裡。已有業務是否能依系統演進程度不斷相容新業務?
- 應用程式層設計
- 例如微前端,例如元件庫,例如
npm install
- webpack優化
- 骨架螢幕
- 路有動態按需載入
- 程式碼層設計
- 寫好高效能React 程式碼?如何利用好Vue3 時間切片?
- 不說了。太初級的浪費慢慢累積就好。
所以,你應該發現了「總是覺得好像少了點什麼」 是少在哪裡了。對,前端效能最佳化不僅是應用層面、程式碼層的最佳化,更重要的是系統層、業務層的最佳化。
看了以上的心理預設,那接下來就進入正式進入主題吧。
嘗試著走完下面這個流程:
效能指標設定(FPS、頁面秒開率、報錯率、請求數等)
效能標準決定
收益評估
診斷清單
優化手法
Hybrid APP 效能最佳化
#NSR
#SSR
webView
舉個栗子。
天貓首頁精選。上圖。 剛好是天貓618活動。這個IOS版的天貓首頁精選。如果你經常造訪天貓首頁精選,你會發現它已經幾乎做到了無痕瀏覽。懶加載在這就被運用的很好,當然,這裡不僅僅是做了懶加載才達到這樣的效果。那隻說懶加載,天貓首頁精選做了什麼呢?猜猜看。
懶載入
圖片是
native假如你快速的進行畫面滾動,
List滾動高度發生很大變化,那請求資料最終還是會敵不過你的高速滑動。也就是說,在沒有新的數據之前你看不到下一張卡片了,這是你必須等待了。這時候就會有一個
loading這裡會有人說了,
IOS的阻尼本來就會使得動畫、滾動效果更加順暢。這裡為想說的是,
Android介面快取
介面快取的實現,如果是端內的話,所有請求都走 Native 請求,以此來實現介面快取。為什麼要這麼做呢? App 中的頁面展現有兩種形式,使用 Native 開發的頁面展現和使用 H5 開發的頁面展現。如果統一使用 Native 做請求的話,已經請求過的資料接口,就不用請求了。而如果使用 H5 請求數據,必須等 WebView 初始化之後才能請求(也就是串行請求),而 Native 請求時,可以在 WebView 初始化之前就開始請求數據(也就是並行請求),這樣能有效節省時間。那麼,如何透過 Native 進行介面快取呢? 我們可以藉助 SDK 封裝來實現,也就是修改原來的資料介面請求方法,實作類似 Axios 的請求方法。具體來說就是,把包含 post、Get 和 Request 功能的接口,封裝進 SDK 中。
這樣,客戶端發起請求時,程式會呼叫SDK.axios 方法,WebView 會攔截這個請求,去查看App 本地是否有資料緩存,如果有的話,就走接口緩存,如果沒有的話,先向服務端請求資料接口,取得接口資料後存放到App 快取。靜態資源快取
先看圖。91 requests,113 kB transferred, 2.2 MB resources,Finish: 2.93 s,DOMContentLoaded: 177 ms.
2.2M的資源,達到秒開。看看Size那一列,就該好像領悟到什麼了。
沒錯。 HTTP快取。資料介面的請求一般來說較少,只有幾個,而靜態資源(如 JS、CSS、圖片和字體等)的請求就太多了。以天貓首頁為例,91 個請求中除了少數script外,其餘都是靜態資源請求。
那麼,如何做靜態快取方案呢?這裡有兩種情況,一種是靜態資源長期不需要修改,還有一種是靜態資源修改頻繁的。你可以嘗試多刷新幾次頁面看看。
資源長期不變的話,例如 1 年都不太變化,我們可以使用強緩存,如 Cache-Control 來實現。具體來說可以透過設定 Cache-Control:max-age=31536000,讓瀏覽器在一年內直接使用本地快取文件,而不是向服務端發出請求。
至於第二種,如果資源本身隨時會改變的,可以透過設定 Etag 來實現協商快取。具體來說,在初次請求資源時,設定 Etag(例如使用資源的 md5 作為 Etag),並且傳回 200 的狀態碼,之後請求時帶上 If-none-match 字段,來詢問伺服器當前版本是否可用。如果服務端資料沒有變化,會傳回 304 的狀態碼給客戶端,告訴客戶端不需要請求數據,直接使用先前快取的資料即可。當然,這裡還涉及 WebView相關的東西,先不細講。 。 。
離線化是指線上即時變動的資源資料靜態化到本地,存取時走的是本地檔案的方案。
離線套件
就是一是離線化的一種方案,是將靜態資源儲存到 App 本地的方案,這裡先不細講。
但更複雜的另一個離線化方案:把頁面內容靜態化到本地。 離線化一般適合首頁或清單頁等不需要登入頁面的場景,同時能夠支援 SEO 功能。
那麼,要如何實現離線化呢?在打包建置時預先渲染頁面,前端請求落到 index.html 上時,已經是渲染過的內容。此時,可以透過 Webpack 的 prerender-spa-plugin 來實現預渲染,進而實現離線化。
Webpack 實作預先渲染的程式碼範例如下:
// webpack.conf.js var path = require('path') var PrerenderSpaPlugin = require('prerender-spa-plugin') module.exports = { // ... plugins: [ new PrerenderSpaPlugin( // 编译后的html需要存放的路径 path.join(__dirname, '../dist'), // 列出哪些路由需要预渲染 [ '/', '/about', '/contact' ] ) ] } // 面试的时候离线化能讲到这,往往就是做死现场,但风险和收益成正比,值得冒险。那就是,你有木有自己的预渲染方案。
如果說懶載入、快取和離線化都是在請求本身搞事情,想盡辦法減少請求或延遲請求,那並行化則是在請求通道上優化問題,解決請求阻塞問題,進而減少首屏時間。
例如廣州打疫苗排隊,新聞上報道如何阻塞。那除了讓群眾錯開打疫苗的時間,還可以增加打疫苗的醫生數量。我們在處理請求阻塞時,也可以增加請求通道數量-借助於HTTP 2.0
的多工方案來解決。
HTTP 1.1
時代,有兩個效能瓶頸點,串列的檔案傳輸和同網域的連線數限制(6個
)。到了HTTP 2.0
時代,因為提供了多路復用的功能,傳輸資料不再使用文字傳輸(文字傳輸必須按順序傳輸,否則接收端不知道字元的順序),而是採用二進位資料幀和流的方式進行傳輸。
其中,訊框是資料接收的最小單位,流是連接中的一個虛擬通道,它可以承載雙向資訊。每個流都會有一個唯一的整數 ID 對資料順序進行標識,這樣接收端收到資料後,可以按照順序對資料進行合併,不會出現順序出錯的情況。所以,在使用流的情況下,不論多少個資源請求,只要建立一個連線即可。
檔案傳輸環節問題解決後,同網域連線數限制問題要怎麼解決呢?以Nginx 伺服器為例,原先因為每個網域有6
個連線數限制,最大並發就是100
個請求,採用HTTP 2.0
之後,現在則可以做到600
,提升了6
倍。
你一定會問,這不是在運維側要做的事情嗎,我們前端開發需要做什麼?我們要改變靜態檔案合併(JS、CSS、圖片檔案)和靜態資源伺服器做網域雜湊這兩種開發方式。
具體來說,使用 HTTP 2.0
多路復用之後,單一檔案可以單獨上線,不需要再做 JS 檔案合併了。 這裡提一個保留問題,用過阿里系的Antd元件庫吧?函式庫每次更新都不是全部更新,可能這次只更新一個Button
元件,再次只更新一個Card
元件。那是如何做到單獨組件單獨發版的呢?
為了解決靜態網域名稱阻塞(這是個性能瓶頸點),需要將靜態網域分為 pic0-pic5,這樣能提升請求並行能力。
雖然透過靜態資源網域雜湊的辦法解決了問題,但DNS 解析時間會變長很多,同時還需要額外的伺服器來滿足。 HTTP 2.0
多路復用解決了這個問題。
更多程式相關知識,請造訪:程式設計入門! !
以上是你值得了解的關於前端效能優化的一些知識點(上)的詳細內容。更多資訊請關注PHP中文網其他相關文章!