首頁  >  文章  >  web前端  >  你值得了解的關於前端效能優化的一些知識點(上)

你值得了解的關於前端效能優化的一些知識點(上)

青灯夜游
青灯夜游轉載
2021-06-28 10:26:022368瀏覽

前端效能優化的目的在於讓頁面載入的更快,為使用者帶來更好的使用者體驗。那麼前端效能要如何優化呢?具體要怎麼做?以下這篇文章就來帶大家來了解一些關於前端效能優化的知識點。

你值得了解的關於前端效能優化的一些知識點(上)

重複看下以下三個問題。

  • 有木頭有不同的人問過你:什麼前端效能最佳化?
  • 有木頭有不同的面試官問過你:你為前端效能優化做過什麼?
  • 有木頭有哪一次,你問過自己:別人問我前端效能優化到底該如何答案
  • 你有木有一套自己的關於性能優化的答案,能讓技術大牛和你一起探討,也能讓小白點頭稱是。

假如你有,那你的答案在哪。

我們先來探討一件事情,一個前端專案如何從構思到落地

例如整個天貓首頁。答案有很多種,你看看有木頭有你想的那種。

  • create-react-app 初始化一個專案吧。首頁寫好一些元件,例如豆腐塊、Header、Bar、長滾動ScrollView。然後專案編譯、打包上線。

  • webpack手搭一個項目。

    • 路由按需載入弄上,可無痕瀏覽的帶loadmore的高效能ScrollList#。

    • 因為是首頁,明顯會牽扯到首畫面載入的問題。那骨架螢幕給安排上吧。

    • 再搞一套webpack的最佳實踐,目的是能最終得到體積盡量小的打包檔案。

    • SSR來一套吧。因為首頁DOM結構太複雜了,如果走Virtual DOM那一套,等到GPU渲染UI就太慢了。

以上,有命中你的某個點嗎?不管有木頭有道理,這是你想到的點嗎?是不是總覺得好像少了點什麼?

本篇文章不細講其它內容。但到這了就得提一嘴,留個印象。

  • 系統層設計
    • 一個新系統留20%來滿足目前已有業務。剩下80% 用來系統演進。可以思考下,天貓首頁一直變,卻仍能保證性能達標。
  • 業務層設計
    • 已有業務是否與其它業務產生了耦合,是否存在前置業務,如果有那前置業務的權限又在哪裡。已有業務是否能依系統演進程度不斷相容新業務?
  • 應用程式層設計
    • 例如微前端,例如元件庫,例如npm install
    • webpack優化
    • 骨架螢幕
    • 路有動態按需載入
  • 程式碼層設計
    • 寫好高效能React 程式碼?如何利用好Vue3 時間切片?
    • 不說了。太初級的浪費慢慢累積就好。

所以,你應該發現了「總是覺得好像少了點什麼」 是少在哪裡了。對,前端效能最佳化不僅是應用層面、程式碼層的最佳化,更重要的是系統層、業務層的最佳化。

看了以上的心理預設,那接下來就進入正式進入主題吧。

效能最佳化流程

嘗試著走完下面這個流程:

  • 效能指標設定(FPS、頁面秒開率、報錯率、請求數等)

    • 如何讓老闆了解你的最佳化方案?假如你的老闆不懂技術。
    • 告訴老闆,頁面白螢幕時間減少了0.4s。
    • 告訴老闆,弱網情況下首頁秒開
    • 告訴老闆,以前http請求量大導致伺服器壓力太大了,現在每個頁面最多只有不到5個請求是向伺服器要資源的。
    • 告訴老闆…
  • 效能標準決定

    • 確認要哪些指標
  • 收益評估

    • 針對老闆滿意程式設計。 /摀臉.png (手動狗頭)
  • 診斷清單

    • 清單上會告訴你各項指標的資料。
  • 優化手法

    • Hybrid APP 效能最佳化

      • App 啟動階段的最佳化方案
      • 頁面白屏階段的最佳化方案
      • #首屏渲染階段的最佳化方案
    • ##首評秒開的X種方法?

        懶載入
      • 快取
      • 離線化
        • #保證首次載入為秒開的離線套件設計
      • 並行化
    • 骨架螢幕

        #元件骨架螢幕
      • 圖片骨架螢幕
    • #NSR

    • #SSR

    • webView

      層及程式碼架構層面最佳化###
      • WebView 效能最佳化
      • 並行初始化
      • 資源預先載入
      • 資料介面請求最佳化
      • ##前端架構效能調優
        • 長列表效能最佳化
        • 打包最佳化
  • 效能立項

    • #確定了就去搞起來吧。
  • 效能實踐
    • 做好準備,盡情的在各種惡劣環境下把頁面快速的折騰出來吧!

小結

現在,你對前端效能最佳化有了完整的認知了嗎?很多時候談論到性能優化首先需要談到如何對性能進行「確診」。雖然大部分的情況,你不會被問到如何監控效能。 (說話聲音越來越小。。。)

接下來就細談優化手段

首屏秒開的多種優化手段

1. 懶載入

最常見的最佳化手段之一。

懶載入是指在長頁面載入過程時,先載入關鍵內容,延遲載入非關鍵內容。例如當我們打開一個頁面,它的內容超過了瀏覽器的可視區口大小,我們可以先加載前端的可視區域內容,剩下的內容等它進入可視區域後再按需加載。

舉個栗子。

天貓首頁精選。上圖。

你值得了解的關於前端效能優化的一些知識點(上)

剛好是天貓618活動。這個IOS版的天貓首頁精選。如果你經常造訪天貓首頁精選,你會發現它已經幾乎做到了無痕瀏覽。懶加載在這就被運用的很好,當然,這裡不僅僅是做了懶加載才達到這樣的效果。

那隻說懶加載,天貓首頁精選做了什麼呢?猜猜看。

懶載入

    • 圖片懶載入
    • 圖片是native
    • 做過快取的。
    • 在可視區域出現才會載入
    • 卡片預先載入(懶載入的時機改變)
    • 並不是進入視覺區域才載入卡片的。而是當上一張卡片進入可視區域就預先加載下一張卡片。因為相對於圖片,載入卡片UI會快得多。這也是無痕瀏覽的保障之一。
    • 動畫懶載入
    • 假如你快速的進行畫面滾動,List滾動高度發生很大變化,那請求資料最終還是會敵不過你的高速滑動。也就是說,在沒有新的數據之前你看不到下一張卡片了,這是你必須等待了。這時候就會有一個loading
    • 的動畫顯示,接著等著拿到了新數據,新卡片就會出現並且自動完全滑入可視區域。
    • 這裡會有人說了,IOS的阻尼本來就會使得動畫、滾動效果更加順暢。這裡為想說的是,Android
    • 也是一樣可以。

2. 快取

如果說懶載入本質是提供首屏後請求非關鍵內容的能力,那麼快取則是賦予二次訪問不需要重複請求的能力。在首屏優化方案中,介面快取和靜態資源快取扮演中流砥柱的角色。

回到剛剛懶加載提到的問題,為什麼你要快速劃屏一段時間才會遇見沒有新數據的情況?原因就是快取的資料已經用完了,所以只能讓伺服器給予最新的資料。
  • 介面快取

    介面快取的實現,如果是端內的話,所有請求都走 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相關的東西,先不細講。 。 。

3. 離線化處理

離線化是指線上即時變動的資源資料靜態化到本地,存取時走的是本地檔案的方案。

離線套件就是一是離線化的一種方案,是將靜態資源儲存到 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' ]
    )
  ]
}
// 面试的时候离线化能讲到这,往往就是做死现场,但风险和收益成正比,值得冒险。那就是,你有木有自己的预渲染方案。

4. 並行化

如果說懶載入、快取和離線化都是在請求本身搞事情,想盡辦法減少請求或延遲請求,那並行化則是在請求通道上優化問題,解決請求阻塞問題,進而減少首屏時間。

例如廣州打疫苗排隊,新聞上報道如何阻塞。那除了讓群眾錯開打疫苗的時間,還可以增加打疫苗的醫生數量。我們在處理請求阻塞時,也可以增加請求通道數量-借助於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中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除