溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

前端性能優(yōu)化的示例分析

發(fā)布時(shí)間:2021-06-28 10:48:08 來(lái)源:億速云 閱讀:166 作者:小新 欄目:web開(kāi)發(fā)

這篇文章給大家分享的是有關(guān)前端性能優(yōu)化的示例分析的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

反復(fù)看下以下三個(gè)問(wèn)題。

  • 有木有不同的人問(wèn)過(guò)你:什么前端性能優(yōu)化?

  • 有木有不同的面試官問(wèn)過(guò)你:你為前端性能優(yōu)化做過(guò)什么?

  • 有木有哪一次,你問(wèn)過(guò)自己:別人問(wèn)我前端性能優(yōu)化到底應(yīng)該如何答復(fù)?

  • 你有木有一套自己的關(guān)于性能優(yōu)化的答案,能讓技術(shù)大牛和你一起探討,也能讓小白點(diǎn)頭稱是。

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

我們先來(lái)探討一件事情,一個(gè)前端項(xiàng)目如何從構(gòu)思到落地

例如整個(gè)天貓首頁(yè)。答案有很多種,你看看有木有你想的那種。

  • create-react-app 初始化一個(gè)項(xiàng)目吧。 首頁(yè)寫好一些組件,例如豆腐塊、Header、Bar、長(zhǎng)滾動(dòng)ScrollView。然后項(xiàng)目編譯、打包上線。

  • webpack手搭一個(gè)項(xiàng)目。

    • 路由按需加載弄上,可無(wú)痕瀏覽的帶loadmore的高性能ScrollList。

    • 因?yàn)槭鞘醉?yè),明顯會(huì)牽扯到首屏幕加載的問(wèn)題。那骨架屏給安排上吧。

    • 再搞一套webpack的最佳實(shí)踐,目的是能最終得到體積盡量小的打包文件。

    • SSR來(lái)一套吧。因?yàn)槭醉?yè)DOM結(jié)構(gòu)太復(fù)雜了,如果走Virtual DOM那一套,等到GPU渲染UI就太慢了。

以上,有命中你的某個(gè)點(diǎn)嗎? 不管有木有道理,這是你想到的點(diǎn)嗎?是不是總感覺(jué)好像少了點(diǎn)什么?

本篇文章不細(xì)講其它內(nèi)容。 但到這了就得提一嘴,留個(gè)印象。

  • 系統(tǒng)層設(shè)計(jì)

    • 一個(gè)新系統(tǒng)留20%來(lái)滿足當(dāng)前已有業(yè)務(wù)。 剩下80% 用來(lái)系統(tǒng)演進(jìn)??梢运伎枷?,天貓首頁(yè)一直變,卻依然能保證性能達(dá)標(biāo)。

  • 業(yè)務(wù)層設(shè)計(jì)

    • 已有業(yè)務(wù)是否與其它業(yè)務(wù)產(chǎn)生了耦合,是否存在前置業(yè)務(wù),如果有那前置業(yè)務(wù)的權(quán)限又在哪里。已有業(yè)務(wù)是否能根據(jù)系統(tǒng)演進(jìn)程度不斷兼容新業(yè)務(wù)?

  • 應(yīng)用層設(shè)計(jì)

    • 例如微前端,例如組件庫(kù),例如npm install

    • webpack優(yōu)化

    • 骨架屏

    • 路有動(dòng)態(tài)按需加載

  • 代碼層設(shè)計(jì)

    • 寫好高性能React 代碼?如何利用好Vue3 時(shí)間切片?

    • 不說(shuō)了。太初級(jí)的浪費(fèi)慢慢積累就好。

所以,你應(yīng)該發(fā)現(xiàn)了“總感覺(jué)好像少了點(diǎn)什么” 是少在哪里了。對(duì),前端性能優(yōu)化不僅僅是應(yīng)用層面、代碼層的優(yōu)化,更重要的是系統(tǒng)層、業(yè)務(wù)層的優(yōu)化。

看了以上的心理預(yù)設(shè),那接下來(lái)就進(jìn)入正式進(jìn)入主題吧。

性能優(yōu)化流程

嘗試著走完下面這個(gè)流程:

  • 性能指標(biāo)設(shè)定(FPS、頁(yè)面秒開(kāi)率、報(bào)錯(cuò)率、請(qǐng)求數(shù)等)

    • 如何讓老板了解你的優(yōu)化方案?假如你的老板不懂技術(shù)。

    • 告訴老板,頁(yè)面白屏?xí)r間減少了0.4s。

    • 告訴老板,弱網(wǎng)情況下首頁(yè)秒開(kāi)。

    • 告訴老板,以前http請(qǐng)求量大導(dǎo)致服務(wù)器壓力太大了,現(xiàn)在每個(gè)頁(yè)面最多只有不到5個(gè)請(qǐng)求是向服務(wù)器要資源的。

    • 告訴老板……

  • 性能標(biāo)準(zhǔn)確定

    • 確認(rèn)要哪些指標(biāo)

  • 收益評(píng)估

    • 面向老板滿意編程。 /捂臉.png (手動(dòng)狗頭)

  • 診斷清單

    • 清單上會(huì)告訴你各項(xiàng)指標(biāo)的數(shù)據(jù)。

  • 優(yōu)化手段

    • WebView 性能優(yōu)化

    • 并行初始化

    • 資源預(yù)加載

    • 數(shù)據(jù)接口請(qǐng)求優(yōu)化

    • 前端架構(gòu)性能調(diào)優(yōu)

    • 長(zhǎng)列表性能優(yōu)化

    • 打包優(yōu)化

    • 組件骨架屏

    • 圖片骨架屏

    • 懶加載

    • 緩存

    • 離線化

    • 并行化

    • 保證首次加載為秒開(kāi)的離線包設(shè)計(jì)

    • App 啟動(dòng)階段的優(yōu)化方案

    • 頁(yè)面白屏階段的優(yōu)化方案

    • 首屏渲染階段的優(yōu)化方案

    • Hybrid APP 性能優(yōu)化

    • 首評(píng)秒開(kāi)的X種方法?

    • 骨架屏

    • NSR

    • SSR

    • webView層及代碼架構(gòu)層面優(yōu)化

  • 性能立項(xiàng)

    • 確定了就去搞起來(lái)吧。

  • 性能實(shí)踐

    • 做好準(zhǔn)備,盡情的在各種惡劣環(huán)境下把頁(yè)面快速的折騰出來(lái)吧!

小結(jié)

現(xiàn)在,你對(duì)前端性能優(yōu)化有了一個(gè)完整的認(rèn)知了嗎?很多時(shí)候談?wù)摰叫阅軆?yōu)化首先需要談到如何對(duì)性能進(jìn)行“確診”。雖然大部分情況,你不會(huì)被人問(wèn)到是如何對(duì)性能進(jìn)行監(jiān)控的。(說(shuō)話聲音越來(lái)越小。。。)

接下來(lái)就細(xì)談優(yōu)化手段

首屏秒開(kāi)的多種優(yōu)化手段

1. 懶加載

最常見(jiàn)的優(yōu)化手段之一。

懶加載是指在長(zhǎng)頁(yè)面加載過(guò)程時(shí),先加載關(guān)鍵內(nèi)容,延遲加載非關(guān)鍵內(nèi)容。比如當(dāng)我們打開(kāi)一個(gè)頁(yè)面,它的內(nèi)容超過(guò)了瀏覽器的可視區(qū)口大小,我們可以先加載前端的可視區(qū)域內(nèi)容,剩下的內(nèi)容等它進(jìn)入可視區(qū)域后再按需加載。

舉個(gè)栗子。天貓首頁(yè)精選。上圖。

前端性能優(yōu)化的示例分析

正好是天貓618活動(dòng)。這個(gè)IOS版的天貓首頁(yè)精選。如果你經(jīng)常訪問(wèn)天貓首頁(yè)精選,你會(huì)發(fā)現(xiàn)它已經(jīng)幾乎做到了無(wú)痕瀏覽。懶加載在這就被運(yùn)用的很好,當(dāng)然,這里不僅僅是做了懶加載才達(dá)到這樣的效果。

那只說(shuō)懶加載,天貓首頁(yè)精選做了什么呢? 猜猜看。

懶加載

  • 圖片懶加載

    • 圖片是native做過(guò)緩存的。

    • 在可視區(qū)域出現(xiàn)才會(huì)加載

  • 卡片預(yù)先加載(懶加載的時(shí)機(jī)改變)

    • 并不是進(jìn)入可視區(qū)域才加載卡片的。而是當(dāng)上一張卡片進(jìn)入可視區(qū)域就預(yù)先加載下一張卡片。 因?yàn)橄鄬?duì)于圖片,加載卡片UI會(huì)快得多。 這也是無(wú)痕瀏覽的保障之一。

  • 動(dòng)畫懶加載

    • 假如你快速的進(jìn)行劃屏滾動(dòng),List滾動(dòng)高度發(fā)生很大變化,那請(qǐng)求數(shù)據(jù)最終還是會(huì)敵不過(guò)你的高速滑動(dòng)。也就是說(shuō),在沒(méi)有新的數(shù)據(jù)之前你看不到下一張卡片了,這是你必須等待了。這時(shí)候就會(huì)有一個(gè)loading的動(dòng)畫顯示,接著等拿到了新數(shù)據(jù),新卡片就會(huì)出現(xiàn)并且自動(dòng)完全滑入可視區(qū)域。

    • 這里會(huì)有人說(shuō)了,IOS的阻尼本來(lái)就會(huì)使得動(dòng)畫、滾動(dòng)效果更加順暢。在這里為想說(shuō)的是,Android也一樣可以。

2. 緩存

如果說(shuō)懶加載本質(zhì)是提供首屏后請(qǐng)求非關(guān)鍵內(nèi)容的能力,那么緩存則是賦予二次訪問(wèn)不需要重復(fù)請(qǐng)求的能力。在首屏優(yōu)化方案中,接口緩存和靜態(tài)資源緩存起到中流砥柱的作用。

回到剛才懶加載提到的那個(gè)問(wèn)題,為什么你要快速劃屏一段時(shí)間才會(huì)遇見(jiàn)沒(méi)有新數(shù)據(jù)的情況?原因就是緩存的數(shù)據(jù)已經(jīng)用完了,所以只能讓服務(wù)器給予最新的數(shù)據(jù)。

  • 接口緩存接口緩存的實(shí)現(xiàn),如果是端內(nèi)的話,所有請(qǐng)求都走 Native 請(qǐng)求,以此來(lái)實(shí)現(xiàn)接口緩存。為什么要這么做呢?

    App 中的頁(yè)面展現(xiàn)有兩種形式,使用 Native 開(kāi)發(fā)的頁(yè)面展現(xiàn)和使用 H5 開(kāi)發(fā)的頁(yè)面展現(xiàn)。如果統(tǒng)一使用 Native 做請(qǐng)求的話,已經(jīng)請(qǐng)求過(guò)的數(shù)據(jù)接口,就不用請(qǐng)求了。而如果使用 H5 請(qǐng)求數(shù)據(jù),必須等 WebView 初始化之后才能請(qǐng)求(也就是串行請(qǐng)求),而 Native 請(qǐng)求時(shí),可以在 WebView 初始化之前就開(kāi)始請(qǐng)求數(shù)據(jù)(也就是并行請(qǐng)求),這樣能有效節(jié)省時(shí)間。

    那么,如何通過(guò) Native 進(jìn)行接口緩存呢?我們可以借助 SDK 封裝來(lái)實(shí)現(xiàn),即修改原來(lái)的數(shù)據(jù)接口請(qǐng)求方法,實(shí)現(xiàn)類似 Axios 的請(qǐng)求方法。具體來(lái)說(shuō)就是,把包括 post、Get 和 Request 功能的接口,封裝進(jìn) SDK 中。

    這樣,客戶端發(fā)起請(qǐng)求時(shí),程序會(huì)調(diào)用 SDK.axios 方法,WebView 會(huì)攔截這個(gè)請(qǐng)求,去查看 App 本地是否有數(shù)據(jù)緩存,如果有的話,就走接口緩存,如果沒(méi)有的話,先向服務(wù)端請(qǐng)求數(shù)據(jù)接口,獲取接口數(shù)據(jù)后存放到 App 緩存中。

  • 靜態(tài)資源緩存先看圖。

前端性能優(yōu)化的示例分析

91 requests,113 kB transferred, 2.2 MB resources,Finish: 2.93 s,DOMContentLoaded: 177 ms.2.2M的資源,達(dá)到秒開(kāi)。看看Size那一列,你就應(yīng)該好像領(lǐng)悟到什么了。

沒(méi)錯(cuò)。HTTP緩存。 數(shù)據(jù)接口的請(qǐng)求一般來(lái)說(shuō)較少,只有幾個(gè),而靜態(tài)資源(如 JS、CSS、圖片和字體等)的請(qǐng)求就太多了。以天貓首頁(yè)為例,91 個(gè)請(qǐng)求中除了少數(shù)script外,其余都是靜態(tài)資源請(qǐng)求。

那么,如何做靜態(tài)緩存方案呢?這里有兩種情況,一種是靜態(tài)資源長(zhǎng)期不需要修改,還有一種是靜態(tài)資源修改頻繁的。你可以嘗試多刷新幾次頁(yè)面看看。

資源長(zhǎng)期不變的話,比如 1 年都不怎么變化,我們可以使用強(qiáng)緩存,如 Cache-Control 來(lái)實(shí)現(xiàn)。具體來(lái)說(shuō)可以通過(guò)設(shè)置 Cache-Control:max-age=31536000,來(lái)讓瀏覽器在一年內(nèi)直接使用本地緩存文件,而不是向服務(wù)端發(fā)出請(qǐng)求。

至于第二種,如果資源本身隨時(shí)會(huì)發(fā)生改動(dòng)的,可以通過(guò)設(shè)置 Etag 實(shí)現(xiàn)協(xié)商緩存。具體來(lái)說(shuō),在初次請(qǐng)求資源時(shí),設(shè)置 Etag(比如使用資源的 md5 作為 Etag),并且返回 200 的狀態(tài)碼,之后請(qǐng)求時(shí)帶上 If-none-match 字段,來(lái)詢問(wèn)服務(wù)器當(dāng)前版本是否可用。如果服務(wù)端數(shù)據(jù)沒(méi)有變化,會(huì)返回一個(gè) 304 的狀態(tài)碼給客戶端,告訴客戶端不需要請(qǐng)求數(shù)據(jù),直接使用之前緩存的數(shù)據(jù)即可。當(dāng)然,這里還涉及 WebView相關(guān)的東西,先不細(xì)講。。。

3. 離線化處理

離線化是指線上實(shí)時(shí)變動(dòng)的資源數(shù)據(jù)靜態(tài)化到本地,訪問(wèn)時(shí)走的是本地文件的方案。

離線包就是一是離線化的一種方案,是將靜態(tài)資源存儲(chǔ)到 App 本地的方案,這里先不細(xì)講。

但更復(fù)雜的另一種離線化方案:把頁(yè)面內(nèi)容靜態(tài)化到本地。離線化一般適合首頁(yè)或者列表頁(yè)等不需要登錄頁(yè)面的場(chǎng)景,同時(shí)能夠支持 SEO 功能。

那么,如何實(shí)現(xiàn)離線化呢?在打包構(gòu)建時(shí)預(yù)渲染頁(yè)面,前端請(qǐng)求落到 index.html 上時(shí),已經(jīng)是渲染過(guò)的內(nèi)容。此時(shí),可以通過(guò) Webpack 的 prerender-spa-plugin 來(lái)實(shí)現(xiàn)預(yù)渲染,進(jìn)而實(shí)現(xiàn)離線化。

Webpack 實(shí)現(xiàn)預(yù)渲染的代碼示例如下:

// webpack.conf.js
var path = require('path')
var PrerenderSpaPlugin = require('prerender-spa-plugin')
module.exports = {
  // ...
  plugins: [
    new PrerenderSpaPlugin(
      // 編譯后的html需要存放的路徑
      path.join(__dirname, '../dist'),
      // 列出哪些路由需要預(yù)渲染
      [ '/', '/about', '/contact' ]
    )
  ]
}
// 面試的時(shí)候離線化能講到這,往往就是做死現(xiàn)場(chǎng),但風(fēng)險(xiǎn)和收益成正比,值得冒險(xiǎn)。那就是,你有木有自己的預(yù)渲染方案。

4. 并行化

如果說(shuō)懶加載、緩存和離線化都是在請(qǐng)求本身搞事情,想盡辦法減少請(qǐng)求或者推遲請(qǐng)求,那并行化則是在請(qǐng)求通道上優(yōu)化問(wèn)題,解決請(qǐng)求阻塞問(wèn)題,進(jìn)而減少首屏?xí)r間。

例如廣州打疫苗排隊(duì),新聞上報(bào)道是如何如何阻塞。 那除了讓群眾錯(cuò)開(kāi)打疫苗的時(shí)間,還可以增加打疫苗的醫(yī)生數(shù)量。我們?cè)谔幚碚?qǐng)求阻塞時(shí),也可以加大請(qǐng)求通道數(shù)量——借助于HTTP 2.0 的多路復(fù)用方案來(lái)解決。

HTTP 1.1 時(shí)代,有兩個(gè)性能瓶頸點(diǎn),串行的文件傳輸和同域名的連接數(shù)限制(6個(gè))。到了HTTP 2.0 時(shí)代,因?yàn)樘峁┝硕嗦窂?fù)用的功能,傳輸數(shù)據(jù)不再使用文本傳輸(文本傳輸必須按順序傳輸,否則接收端不知道字符的順序),而是采用二進(jìn)制數(shù)據(jù)幀和流的方式進(jìn)行傳輸。

其中,幀是數(shù)據(jù)接收的最小單位,流是連接中的一個(gè)虛擬通道,它可以承載雙向信息。每個(gè)流都會(huì)有一個(gè)唯一的整數(shù) ID 對(duì)數(shù)據(jù)順序進(jìn)行標(biāo)識(shí),這樣接收端收到數(shù)據(jù)后,可以按照順序?qū)?shù)據(jù)進(jìn)行合并,不會(huì)出現(xiàn)順序出錯(cuò)的情況。所以,在使用流的情況下,不論多少個(gè)資源請(qǐng)求,只要建立一個(gè)連接即可。

文件傳輸環(huán)節(jié)問(wèn)題解決后,同域名連接數(shù)限制問(wèn)題怎么解決呢?以 Nginx 服務(wù)器為例,原先因?yàn)槊總€(gè)域名有6個(gè)連接數(shù)限制,最大并發(fā)就是 100 個(gè)請(qǐng)求,采用 HTTP 2.0 之后,現(xiàn)在則可以做到 600,提升了 6倍。

你一定會(huì)問(wèn),這不是運(yùn)維側(cè)要做的事情嗎,我們前端開(kāi)發(fā)需要做什么?我們要改變靜態(tài)文件合并(JS、CSS、圖片文件)和靜態(tài)資源服務(wù)器做域名散列這兩種開(kāi)發(fā)方式。

具體來(lái)說(shuō),使用 HTTP 2.0 多路復(fù)用之后,單個(gè)文件可以單獨(dú)上線,不需要再做 JS 文件合并了。這里提一個(gè)保留問(wèn)題,用過(guò)阿里系的Antd組件庫(kù)吧?庫(kù)每次更新都不是全部更新,可能這次只更新一個(gè)Button組件,再次只更新一個(gè)Card組件。那是如何做到單獨(dú)組件單獨(dú)發(fā)版的呢?

為了解決靜態(tài)域名阻塞(這是個(gè)性能瓶頸點(diǎn)),需要將靜態(tài)域名分為 pic0-pic5,這樣能提升請(qǐng)求并行能力。 雖然通過(guò)靜態(tài)資源域名散列的辦法解決了問(wèn)題,但DNS 解析時(shí)間會(huì)變長(zhǎng)很多,同時(shí)還需要額外的服務(wù)器來(lái)滿足。HTTP 2.0 多路復(fù)用解決了這個(gè)問(wèn)題。

感謝各位的閱讀!關(guān)于“前端性能優(yōu)化的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI