1. Web頁(yè)面全鏈路性能優(yōu)化指南

        共 7274字,需瀏覽 15分鐘

         ·

        2022-05-22 09:52

        性能優(yōu)化不單指優(yōu)化一個(gè)頁(yè)面的打開(kāi)速度,在開(kāi)發(fā)環(huán)境將一個(gè)項(xiàng)目的啟動(dòng)時(shí)間縮短使開(kāi)發(fā)體驗(yàn)更好也屬于性能優(yōu)化,大文件上傳時(shí)為其添加分片上傳、斷點(diǎn)續(xù)傳也屬于性能優(yōu)化。在項(xiàng)目開(kāi)發(fā)以及用戶使用的過(guò)程中,能夠讓任何一個(gè)鏈路快一點(diǎn),都可以被叫做性能優(yōu)化。

        本文會(huì)對(duì)web頁(yè)面的全鏈路進(jìn)行完整的講解并針對(duì)每一步找到能做的性能優(yōu)化點(diǎn),本文的目標(biāo)是極致的性能優(yōu)化。

        因?yàn)獒槍?duì)性能優(yōu)化,能做的點(diǎn)會(huì)特別特別的多,覆蓋著整個(gè)互聯(lián)網(wǎng)的訪問(wèn)流程,因此此文章的內(nèi)容會(huì)比較多且雜,筆者會(huì)盡量對(duì)內(nèi)容進(jìn)行分類講解。

        本文的大致流程為先講理論知識(shí),比如如何評(píng)價(jià)一個(gè)頁(yè)面的性能好與不好、如果獲取性能指標(biāo),如何使用各種性能相關(guān)工具,瀏覽器如何獲取并渲染頁(yè)面。筆者認(rèn)為這些都是基礎(chǔ),只有了解了這些基礎(chǔ)才能開(kāi)始考慮如何去優(yōu)化。

        接下來(lái)我們會(huì)進(jìn)入性能優(yōu)化環(huán)節(jié),在這個(gè)環(huán)節(jié)我會(huì)詳細(xì)講解在頁(yè)面的整個(gè)流程中,哪些地方可以做哪些優(yōu)化。

        目錄


        • 進(jìn)程與線程

        • 輸入url到頁(yè)面展示完整過(guò)程

          • 1.用戶輸入

          • 2.卸載原頁(yè)面并重定向到新頁(yè)面

          • 3.處理Service Worker

          • 4.網(wǎng)絡(luò)請(qǐng)求

          • 5.服務(wù)端響應(yīng)

          • 6.瀏覽器渲染詳細(xì)流程

        • 瀏覽器處理每一幀的流程

        • Chrome Performance(性能)

          • Chrome Performance 工具的使用

          • Performance API介紹

          • 使用Performance API獲取性能相關(guān)指標(biāo)

        • Coverage(覆蓋率)

        • Lighthouse

        • Network(網(wǎng)絡(luò))

          • 網(wǎng)絡(luò)請(qǐng)求中的Timing(時(shí)間)

          • 網(wǎng)絡(luò)請(qǐng)求的優(yōu)先級(jí)

          • 網(wǎng)頁(yè)總資源信息

          • Network配置

        • 網(wǎng)絡(luò)優(yōu)化策略

          • 減少HTTP請(qǐng)求數(shù)

          • 使用HTTP緩存

          • 使用 HTTP/2.0

          • 避免重定向

          • 使用 dns-prefetch

          • 使用域名分片

          • CDN

          • 壓縮

          • 使用contenthash

          • 合理使用preload、prefetch

        • 瀏覽器渲染優(yōu)化策略

          • 關(guān)鍵渲染路徑

          • 強(qiáng)制同步布局問(wèn)題

          • 如何減少重排與重繪

        • 靜態(tài)文件優(yōu)化策略

          • 圖片格式

          • 圖片優(yōu)化

          • HTML優(yōu)化

          • CSS優(yōu)化

          • JS優(yōu)化

          • 字體優(yōu)化

        • 瀏覽器儲(chǔ)存優(yōu)化策略

          • Cookie

          • LocalStorage

          • SessionStorage

          • IndexDB

        • 其他優(yōu)化策略

        • 使用PWA提高用戶體驗(yàn)


        瀏覽器渲染原理

        我們需要知道瀏覽器是如何渲染一個(gè)頁(yè)面的,我們才能知道如何對(duì)頁(yè)面進(jìn)行性能優(yōu)化,所以這里我們對(duì)一些基礎(chǔ)知識(shí)進(jìn)行講解

        進(jìn)程與線程

        瀏覽器有多種進(jìn)程,其中最主要的5種進(jìn)程如下

        1. 瀏覽器進(jìn)程 負(fù)責(zé)界面展示、用戶交互、子進(jìn)程管理、提供存儲(chǔ)等
        2. 渲染進(jìn)程 每個(gè)頁(yè)面都有一個(gè)單獨(dú)的渲染進(jìn)程,用于渲染頁(yè)面,包含webworker線程
        3. 網(wǎng)絡(luò)進(jìn)程 主要處理網(wǎng)絡(luò)資源加載(HTML、CSS、JS、IMAGE、AJAX等)
        4. GPU進(jìn)程 3D繪制,提高性能
        5. 插件進(jìn)程 chrome插件,每個(gè)插件占用一個(gè)進(jìn)程

        輸入url到頁(yè)面展示完整過(guò)程

        圖1

        圖1

        1.用戶輸入

        用戶在瀏覽器進(jìn)程輸入并按下回車健后,瀏覽器判斷用戶輸入的url是否為正確的url,如果不是,則使用默認(rèn)的搜索引擎將該關(guān)鍵字拼接成url。

        2.卸載原頁(yè)面并重定向到新頁(yè)面

        然后瀏覽器會(huì)將現(xiàn)有頁(yè)面卸載掉并重定向到用戶新輸入的url頁(yè)面,也就是圖中【Process Unload Event】和【Redirect】流程。

        此時(shí)瀏覽器會(huì)準(zhǔn)備一個(gè)渲染進(jìn)程用于渲染即將到來(lái)的頁(yè)面,和一個(gè)網(wǎng)絡(luò)進(jìn)程用于發(fā)送網(wǎng)絡(luò)請(qǐng)求。

        3.處理Service Worker

        如果當(dāng)前頁(yè)面注冊(cè)了Service Worker那么它可以攔截當(dāng)前網(wǎng)站所有的請(qǐng)求,進(jìn)行判斷是否需要向遠(yuǎn)程發(fā)送網(wǎng)絡(luò)請(qǐng)求。也就是圖中【Service Worker Init】與【Service Worker Fecth Event 】步驟

        如果不需要發(fā)送網(wǎng)絡(luò)請(qǐng)求,則取本地文件。如果需要?jiǎng)t進(jìn)行下一步。

        4.網(wǎng)絡(luò)請(qǐng)求

        OSI網(wǎng)絡(luò)七層模型:物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、會(huì)話層、表示層、應(yīng)用層

        在實(shí)際應(yīng)用中物理層、數(shù)據(jù)鏈路層被統(tǒng)稱為物理層,會(huì)話層、表示層、應(yīng)用層被統(tǒng)稱為應(yīng)用層,所以實(shí)際使用時(shí)通常分為4個(gè)層級(jí)

        【物理層】>【網(wǎng)絡(luò)層(IP)】>【傳輸層(TCP/UDP)】>【應(yīng)用層(HTTP)】

        也就是圖中【HTTP Cache】、【DNS】、【TCP】、【Request】、【Response】步驟

        圖2

        圖2

        瀏覽器會(huì)拿著url通過(guò)網(wǎng)絡(luò)進(jìn)程進(jìn)行如下步驟

        1. 根據(jù)url查詢本地是否已經(jīng)有強(qiáng)制緩存,如果有則判斷緩存是否過(guò)期,如果沒(méi)過(guò)期則直接返回緩存內(nèi)容,也就是圖1中【HTTP Cache】步驟

        2. 如果沒(méi)有強(qiáng)制緩存或者緩存已過(guò)期,則將該請(qǐng)求加入隊(duì)列進(jìn)行排隊(duì)準(zhǔn)備發(fā)送網(wǎng)絡(luò)請(qǐng)求,也就是圖2中【正在排隊(duì)】,然后進(jìn)入DNS解析階段,也就是圖1中【DNS】以及圖2中的【DNS查找】,DNS根據(jù)域名解析出對(duì)應(yīng)的IP地址。(DNS基于UDP)。

        3. 然后使用IP尋址找到對(duì)方,然后根據(jù)IP地址+端口號(hào)創(chuàng)建一個(gè)TCP連接(三次握手),也就是圖1中【TCP】以及圖2中的【初始連接】創(chuàng)建完成后利用TCP連接來(lái)傳輸數(shù)據(jù)。(TCP會(huì)將數(shù)據(jù)拆分為多個(gè)數(shù)據(jù)包,進(jìn)行有序傳輸,如果丟包會(huì)重發(fā),TCP的特點(diǎn)是可靠、有序)

        4. 判斷當(dāng)前協(xié)議是否為https,如果為https,則進(jìn)行SSL協(xié)商,將數(shù)據(jù)進(jìn)行加密,如果為http協(xié)議則不進(jìn)行加密(明文傳輸),也就是圖2中的【SSL】。

        5. 開(kāi)始發(fā)送http請(qǐng)求(請(qǐng)求行/請(qǐng)求頭/請(qǐng)求體),也就是圖1中【Request】以及圖2中的【已發(fā)送請(qǐng)求】。HTTP協(xié)議有多個(gè)版本,目前使用最多的版本為HTTP/1.1,HTTP/1.1發(fā)送完成后默認(rèn)不會(huì)斷開(kāi)。keep-alive 默認(rèn)打開(kāi),為了下次傳輸數(shù)據(jù)時(shí)復(fù)用上次創(chuàng)建的連接。每個(gè)域名最多同時(shí)建立6個(gè)TCP連接,所以同一時(shí)間最多發(fā)生6個(gè)請(qǐng)求。

          HTTP協(xié)議的各個(gè)版本特性如下:

          • HTTP/0.9 沒(méi)有請(qǐng)求頭和響應(yīng)頭,不區(qū)分傳輸?shù)膬?nèi)容類型,因?yàn)楫?dāng)時(shí)只傳輸HTML。
          • HTTP/1.0 提供了請(qǐng)求頭和響應(yīng)頭,可以傳輸不同類型的內(nèi)容數(shù)據(jù)。根據(jù)請(qǐng)求響應(yīng)頭的不同來(lái)處理不同的資源,HTTP1.0每次發(fā)完請(qǐng)求都會(huì)斷開(kāi)TCP連接。有新的請(qǐng)求時(shí)再次創(chuàng)建TCP連接。
          • HTTP/1.1 默認(rèn)開(kāi)啟了 keep-alive ,它能夠讓一個(gè)TCP連接中傳輸多個(gè)HTTP請(qǐng)求,也叫鏈路復(fù)用。但一個(gè)TCP連接同一時(shí)間只能發(fā)送一個(gè)HTTP請(qǐng)求,為了不阻塞多個(gè)請(qǐng)求,Chrome允許創(chuàng)建6個(gè)TCP連接,所以在HTTP/1.1中,最多能夠同時(shí)發(fā)送6個(gè)網(wǎng)絡(luò)請(qǐng)求。
          • HTTP/2.0 HTTP/2.0使用同一個(gè)TCP連接來(lái)發(fā)送數(shù)據(jù),他把多個(gè)請(qǐng)求通過(guò)二進(jìn)制分貞層實(shí)現(xiàn)了分貞,然后把數(shù)據(jù)傳輸給服務(wù)器。也叫多路復(fù)用,多個(gè)請(qǐng)求復(fù)用同一個(gè)TCP連接。HTTP/2.0會(huì)將所有以:開(kāi)頭的請(qǐng)求頭做一個(gè)映射表,然后使用hpack進(jìn)行壓縮,使用這種方式會(huì)使請(qǐng)求頭更小。服務(wù)器可主動(dòng)推送數(shù)據(jù)給客戶端。
          • HTTP/3.0 使用UDP實(shí)現(xiàn),在UDP上一層加入一層QUIC協(xié)議,解決了TCP協(xié)議中的隊(duì)頭阻塞問(wèn)題。
        6. 服務(wù)器收到數(shù)據(jù)后解析HTTP請(qǐng)求(請(qǐng)求行/請(qǐng)求頭/請(qǐng)求體),處理完成后生成狀態(tài)碼和HTTP響應(yīng)(響應(yīng)行/響應(yīng)頭/響應(yīng)體)后返回給客戶端,也就是圖2的【等待中】在做的事情。

        7. 客戶端接收到HTTP響應(yīng)后根據(jù)狀態(tài)碼進(jìn)行對(duì)應(yīng)的處理,如果狀態(tài)碼為304則直接代表協(xié)商緩存生效,直接取本地的緩存文件。如果不是則下載內(nèi)容。也就是圖1中【Response】以及圖2中的【下載內(nèi)容】步驟。

        5.服務(wù)端響應(yīng)

        4.網(wǎng)絡(luò)請(qǐng)求6步中,服務(wù)器收到HTTP請(qǐng)求后需要根據(jù)請(qǐng)求信息來(lái)進(jìn)行解析,并返回給客戶端想要的數(shù)據(jù),這也就服務(wù)端響應(yīng)。

        服務(wù)端可以響應(yīng)并返回給客戶端很多種類型的資源,這里主要介紹html類型

        目前前端處理服務(wù)端響應(yīng)html請(qǐng)求主要分為SSR服務(wù)端渲染與CSR客戶端渲染,CSR就是返回一個(gè)空的HTML模版,然后瀏覽器加載js后通過(guò)js動(dòng)態(tài)渲染頁(yè)面。SSR是服務(wù)端在接受到請(qǐng)求時(shí)事先在服務(wù)端渲染好html返回給客戶端后,客戶端再進(jìn)行客戶端激活。

        在打開(kāi)一個(gè)站點(diǎn)的首屏頁(yè)的完整鏈路中,使用SSR服務(wù)端渲染時(shí)的速度要遠(yuǎn)大于CSR客戶端渲染,并且SSR對(duì)SEO友好。所以對(duì)于首屏加載速度比較敏感或者需要優(yōu)化SEO的站點(diǎn)來(lái)說(shuō),使用SSR是更好的選擇。

        6.瀏覽器渲染詳細(xì)流程

        瀏覽器渲染詳細(xì)流程主要在4.網(wǎng)絡(luò)請(qǐng)求中的地7步。瀏覽器下載完html內(nèi)容后進(jìn)行解析何渲染頁(yè)面的流程。

        渲染流程分為4種情況,

        1. HTML中無(wú)任何CSS相關(guān)標(biāo)簽
        2. CSS相關(guān)標(biāo)簽在HTML最頂部,且在解析到內(nèi)容標(biāo)簽(
          )時(shí)已經(jīng)解析完CSS相關(guān)標(biāo)簽
        3. CSS相關(guān)標(biāo)簽在HTML最頂部,但在解析到內(nèi)容標(biāo)簽(
          )時(shí)CSS相關(guān)標(biāo)簽尚未解析完
        4. CSS相關(guān)標(biāo)簽在HTML最底部

        下面的流程是對(duì)上圖的文字版解析。讀者可將以上4種情況分別帶入到如下的渲染流程中走一遍。就能理解瀏覽器的完整渲染過(guò)程了。

        【HTML】

        瀏覽器收到html資源后先預(yù)掃描


        我們遵循讀寫(xiě)分離的原則,將讀取位置操作放到函數(shù)外,我們可以發(fā)現(xiàn)就算循環(huán)插入10個(gè)dom節(jié)點(diǎn),也只需要執(zhí)行一次【計(jì)算樣式】和【重排】。

        如何減少重排與重繪

        1. 脫離文檔流(絕對(duì)定位、固定定位),脫離文檔流的元素進(jìn)行重排不會(huì)影響到其他元素。
        2. 圖片渲染時(shí)增加寬高屬性,寬高固定后,圖片不會(huì)根據(jù)內(nèi)容動(dòng)態(tài)改變高度,便不會(huì)觸發(fā)重排。
        3. 盡量用CSS3動(dòng)畫(huà),CSS3動(dòng)畫(huà)能最大程度減少重排與重繪。
        4. 使用will-change: transform;將元素獨(dú)立為一個(gè)單獨(dú)的圖層。(定位、透明、transform、clip都會(huì)產(chǎn)生獨(dú)立圖層)

        靜態(tài)文件優(yōu)化策略

        圖片格式

        jpeg

        適合色彩豐富的圖、Banner圖。不適合:圖形文字、圖標(biāo)、不支持透明度。

        png

        適合純色、透明、圖標(biāo),支持純透明和半透明。不適合色彩豐富圖片,因?yàn)闊o(wú)損儲(chǔ)存會(huì)導(dǎo)致儲(chǔ)存體積大于jpeg

        gif

        適合動(dòng)畫(huà)、可以動(dòng)的圖標(biāo)。支持純透明但不支持半透明,不適合色彩豐富的圖片。

        埋點(diǎn)信息通常也會(huì)使用gif發(fā)送,因?yàn)?x1的gif圖發(fā)送的網(wǎng)絡(luò)請(qǐng)求比普通的get請(qǐng)求要小一些。

        webp

        支持純透明和半透明,可以保證圖片質(zhì)量和較小的體積,適合Chrome和移動(dòng)端瀏覽器。不適合其他瀏覽器。

        svg

        矢量格式,大小非常小,但渲染成本過(guò)高,適合小且色彩單一的圖標(biāo)。

        圖片優(yōu)化

        • 減少圖片資源的尺寸和大小,節(jié)約用戶流量
        • 設(shè)置alt="xxx"屬性,圖像無(wú)法顯示時(shí)會(huì)顯示alt內(nèi)容
        • 圖片懶加載, loading="lazy"為原生,建議使用IntersectionObserver自己做懶加載
        • 不同環(huán)境加載不同尺寸和像素的圖片srcsetsizes的使用。
        • 采用漸進(jìn)式加載 先加載占位圖,然后加載模糊小圖,最后加載真正清晰的圖
        • 使用Base64URL 減少圖片請(qǐng)求數(shù)
        • 采用雪碧圖合并圖片,減少請(qǐng)求數(shù)。

        HTML優(yōu)化

        • 語(yǔ)義化HTML,代碼簡(jiǎn)潔清晰,利于SEO,便于開(kāi)發(fā)維護(hù)。
        • 減少HTML嵌套關(guān)系,減少DOM節(jié)點(diǎn)數(shù)量。
        • 提前聲明字符編碼,讓瀏覽器快速確定如何渲染網(wǎng)頁(yè)內(nèi)容
        • 刪除多余空格、空行、注釋、無(wú)用屬性
        • 減少iframe,子iframe會(huì)阻塞父級(jí)的onload事件??梢允褂胘s動(dòng)態(tài)給iframe賦值,就能解決這個(gè)問(wèn)題。
        • 避免table布局

        CSS優(yōu)化

        • 減少偽類選擇器,減少選擇器層數(shù)、減少通配符選擇器、減少正則選擇器
        • 避免css表達(dá)式background-color: expression(...)
        • 刪除空格、空行、注釋、減少無(wú)意義的單位、css壓縮
        • css外鏈,能走緩存
        • 添加媒體字段,只加載有效的css文件
        <link?rel="stylesheet"?href="./small.css"?media="screen?and?(max-width:600px)"?/>
        <link?rel="stylesheet"?href="./big.css"?media="screen?and?(min-width:601px)"/>
        • 使用css contain屬性,能控制對(duì)應(yīng)元素是否根據(jù)子集元素的改變進(jìn)行重排
        • 減少@import使用,因?yàn)樗褂么屑虞d

        JS優(yōu)化

        • 通過(guò)script的async、defer屬性異步加載,不阻塞DOM渲染
        • 減少DOM操作,緩存訪問(wèn)過(guò)的元素。
        • 不直接操作真實(shí)DOM,可以先修改,然后一次性應(yīng)用到DOM上。(虛擬DOM、DOM碎片節(jié)點(diǎn))
        • 使用webworker解決復(fù)雜運(yùn)算,避免復(fù)雜運(yùn)算阻塞主線程,webworker線程位于渲染進(jìn)程
        • 圖片懶加載,使用IntersectionObserver實(shí)現(xiàn)
        html>
        <html?lang="en">
        ??<head>
        ????<meta?charset="UTF-8"?/>
        ????<meta?http-equiv="X-UA-Compatible"?content="IE=edge"?/>
        ????<meta?name="viewport"?content="width=device-width,?initial-scale=1.0"?/>
        ????<style>
        ??????img?{
        ????????height:?200px;
        ????????display:?block;
        ??????}
        ????
        style>
        ????<title>Documenttitle>
        ??head>
        ??<body>
        ????<img?src="./loading.gif"?src="./01.jpg"?/>
        ????<img?src="./loading.gif"?src="./02.jpg"?/>
        ????<img?src="./loading.gif"?src="./03.jpg"?/>
        ????<img?src="./loading.gif"?src="./04.jpg"?/>
        ????<img?src="./loading.gif"?src="./05.jpg"?/>
        ????<img?src="./loading.gif"?src="./06.jpg"?/>
        ????<img?src="./loading.gif"?src="./07.jpg"?/>
        ????<img?src="./loading.gif"?src="./08.jpg"?/>
        ????<img?src="./loading.gif"?src="./09.jpg"?/>
        ????<img?src="./loading.gif"?src="./10.jpg"?/>

        ????<script>
        ??????const?intersectionObserver?=?new?IntersectionObserver((changes)?=>?{
        ????????changes.forEach((item,?index)?=>?{
        ??????????if?(item.intersectionRatio?>?0)?{
        ????????????intersectionObserver.unobserve(item.target)
        ????????????item.target.src?=?item.target.dataset.src
        ??????????}
        ????????})
        ??????});

        ??????const?domImgList?=?document.querySelectorAll("img");
        ??????domImgList.forEach((domImg)?=>?intersectionObserver.observe(domImg));
        ????
        script>
        ??body>
        html>

        • 虛擬滾動(dòng)
        • 使用requestAnimationFrame來(lái)做動(dòng)畫(huà),使用requestIdleCallback來(lái)進(jìn)行空閑時(shí)的任務(wù)處理
        • 盡量避免使用eval,性能差。
        • 使用事件委托,能減少事件綁定個(gè)數(shù)。事件越多性能越差。
        • 盡量使用canvas、css3動(dòng)畫(huà)。
        • 通過(guò)chrome覆蓋率(Coverage)工具排查代碼中未使用過(guò)的代碼并將其刪除
        • 通過(guò)chrome性能(Performance)工具查看每個(gè)函數(shù)的執(zhí)行性能并優(yōu)化

        字體優(yōu)化

        FOUT(Flash of Unstyled Text)等待一段時(shí)間,如果沒(méi)加載完成,先顯示默認(rèn)。加載 后再進(jìn)行切換。

        FOIT(F1ash of Invisib1e Text) 字體加載完畢后顯示,加載超時(shí)降級(jí)系統(tǒng)字體(白 屏

        html>
        <html?lang="en">
        <head>
        ??<meta?charset="UTF-8">
        ??<meta?http-equiv="X-UA-Compatible"?content="IE=edge">
        ??<meta?name="viewport"?content="width=device-width,?initial-scale=1.0">
        ??<style>
        ????@font-face?{
        ??????font-family:?'hagan';
        ??????src:?url('./font.ttc');
        ??????font-display:?swap;
        ??????/*?b1ock?35?內(nèi)不顯示,如果沒(méi)加載完畢用默認(rèn)的?*/
        ??????/*?swap?顯示老字體?在替換*/
        ??????/*?fa11back?縮短不顯示時(shí)間,如果沒(méi)加載完畢用默認(rèn)的,和b1ock類似*
        ??????/*?optional?替換可能用字體?可能不替換*/

        ????}
        ????article?{
        ??????font-family:?hagan;
        ????}
        ??
        style>
        ??<title>Documenttitle>
        head>
        <body>
        ??<article>ABC?abcarticle>??
        body>
        html>

        瀏覽器儲(chǔ)存優(yōu)化策略

        Cookie

        cookie在過(guò)期之前一直有效,最大儲(chǔ)存大小為4k,限制字段個(gè)數(shù),不適合大量的數(shù)據(jù)儲(chǔ)存,每次請(qǐng)求會(huì)攜帶cookie,主要用來(lái)做身份校驗(yàn)。

        優(yōu)化方式:

        1. 需要合理設(shè)置cookie有效期
        2. 根據(jù)不同子域劃分cookie來(lái)減少cookie傳輸
        3. 靜態(tài)資源域名和cookie域名采用不同域名,避免靜態(tài)資源請(qǐng)求攜帶cookie。

        LocalStorage

        Chrome下最多儲(chǔ)存5M,除非手動(dòng)清除,否則一直存在??梢岳?code style="font-size: 14px;word-wrap: break-word;border-radius: 4px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #9b6e23;background-color: #fff5e3;padding: 3px;margin: 3px;">localStorage儲(chǔ)存靜態(tài)資源。比如儲(chǔ)存網(wǎng)頁(yè)的.js、.css,這樣會(huì)使頁(yè)面打開(kāi)速度非???。例如 https://m.baidu.com

        /index.js

        const?name?=?'hagan'
        function?showName?()?{
        ??console.log(name)
        }
        showName()

        /index.html

        html>
        <html?lang="en">
        <head>
        ??<meta?charset="UTF-8">
        ??<meta?http-equiv="X-UA-Compatible"?content="IE=edge">
        ??<meta?name="viewport"?content="width=device-width,?initial-scale=1.0">
        ??<title>Documenttitle>
        head>
        <body>
        ??<script?src="https://lib.baomitu.com/axios/0.26.1/axios.js">script>
        ??<script>
        ????cacheFile('/index.js')

        ????async?function?cacheFile?(url)?{
        ??????const?fileContent?=?localStorage.getItem(url)
        ??????if?(fileContent)?{
        ????????eval(fileContent)
        ??????}?else?{
        ????????const?{?data?}?=?await?axios.get(url)
        ????????eval(data)
        ????????localStorage.setItem(url,?data)
        ??????}
        ????}
        ??
        script>
        body>
        html>

        SessionStorage

        會(huì)話級(jí)別儲(chǔ)存,可用于頁(yè)面間的傳值

        IndexDB

        瀏覽器的本地?cái)?shù)據(jù)庫(kù),大小幾乎無(wú)上限

        其他優(yōu)化策略

        • 關(guān)鍵資源個(gè)數(shù)越多,首次頁(yè)面加載時(shí)間就會(huì)越長(zhǎng)
        • 關(guān)鍵資源的大小,內(nèi)容越小下載時(shí)間越短。
        • 優(yōu)化白屏,合理使用內(nèi)聯(lián)css、js
        • 預(yù)渲染,打包時(shí)進(jìn)行預(yù)渲染,生成靜態(tài)HTML文件,用戶訪問(wèn)時(shí)直接返回靜態(tài)HTML。
        • 服務(wù)端渲染同構(gòu),加速首屏速度(耗費(fèi)服務(wù)端資源),有利于SEO優(yōu)化。首屏使用服務(wù)端渲染,后續(xù)交互使用客戶端渲染。

        使用PWA提高用戶體驗(yàn)

        webapp用戶體驗(yàn)差的一大原因是不能離線訪問(wèn)。用戶粘性低的一大原因是無(wú)法保存入口,PWA就是為了解決webapp的用戶體驗(yàn)問(wèn)題而誕生的。使用PWA能令站點(diǎn)擁有快速、可靠、安全等特性。

        1. Web App Manifest 將網(wǎng)站添加到電腦桌面、手機(jī)桌面,類似Native的體驗(yàn)。
        2. Service Worker 配合Cache API,能做到離線緩存各種內(nèi)容。
        3. Push API 配合 Notification API,能做到類似Native的消息推送與實(shí)時(shí)提醒。
        4. App Shell 配合 App Skeleton,能做App殼與骨架屏

        參考資料

        • https://www.w3.org/TR/navigation-timing-2/

        瀏覽 53
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 国产黄色视频免费在线观看 | 亚洲性按摸 | 办公室激情含乳呻吟视频动图 | 欧美变态前列腺高潮 | 艹逼网站 |