<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                &emsp;&emsp;在遇到一個頁面性能問題時,我理解的優化閉環是:分析、策略、驗證和沉淀。 * 分析需要有分析數據,因此得有一個性能監控管理。 * 策略就是制訂針對性的優化方案,解決當前遇到的問題。 * 驗證的對象上述策略,判斷方案是否有效,同樣需要數據支撐。 * 沉淀就是將解決過程文檔化、通用化,能夠總結成一套實際方案、優化規則等。 &emsp;&emsp;這其中非常關鍵的一步是需要采集到性能數據,并且得有個可視化后臺查看數據變化。 &emsp;&emsp;在之前已經自制了一個[性能優化平臺](https://www.cnblogs.com/strick/p/14578711.html),采集前端性能參數的 SDK 叫[shin.js](https://github.com/pwstrick/shin-admin/blob/main/public/shin.js#L226)。 ## 一、優化的三部分 &emsp;&emsp;在文章開頭,我想先聊聊網頁優化的三部分:網絡,渲染和容器。 &emsp;&emsp;第一部分的網絡就是提升傳輸速度,可優化的手段包括 gzipped壓縮、CDN、HTTP 緩存、HTTP 2.0協議、并發請求等。 &emsp;&emsp;像 HTTP 緩存分為強緩存和協商緩存,請求首部和瀏覽器配合完成資源的緩存機制,下圖摘自《[前端程序員面試筆試寶典](https://book.douban.com/subject/30324146/)》。 :-: ![](https://img.kancloud.cn/39/89/3989d605b85acedbafec9741e2eb64e1_960x242.png =600x) &emsp;&emsp;第二部分的渲染就是 CRP 優化(關鍵渲染路徑),CRP 是指瀏覽器從接收資源到渲染像素的過程。 &emsp;&emsp;優化的點包括資源數、字節數和加載時序。現代化的 webpack 構建工具就會對資源做前兩項的優化處理,包括壓縮文件、合并文件、優化包的引入等。 &emsp;&emsp;加載時序就包括日常都會用的圖片懶加載和預加載、腳本的延遲(defer)、異步(async)和預加載([preload](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Link_types/preload))等。 &emsp;&emsp;對于比較龐大的首頁,可以先將那些能阻塞網頁首次渲染的關鍵資源載入,其余資源都延遲載入,以此提升頁面打開速度。 &emsp;&emsp;第三部分的容器(WebView)就是借用端的能力,讓 APP 配合優化網頁。 &emsp;&emsp;例如[預請求](https://www.cnblogs.com/strick/p/14918217.html),將請求接口的時機前置到容器打開之時,下面是一張實現流程圖。 :-: ![](https://img.kancloud.cn/9b/f8/9bf87beac1a3f77c86445fe860c811ac_705x750.png =600x) &emsp;&emsp;還有一種靜態資源緩存至客戶端本地,當時與公司客戶端討論此方案時,他們覺得每次攔截請求會損傷性能,后面就采用了折中的辦法。 &emsp;&emsp;就是他們去主動請求特定地址的靜態資源,然后開放接口讓我可以去讀取本地資源,也就是說由 Web 來控制是否讀取緩存資源。 ## 二、問題引出   &emsp;&emsp;現在言歸正傳,回到本次的優化中來。 &emsp;&emsp;為了提升頁面產出率,聯合 UI 設計構建了一套可配置的[通用活動模板](https://www.cnblogs.com/strick/p/15928830.html)。 &emsp;&emsp;活動上線后,就查看了性能數據,情況很不理想,如下圖所示。 ![](https://img.kancloud.cn/ac/38/ac3812ce8a686e3a8680190f71292f03_2518x842.png =800x) &emsp;&emsp;FP(白屏)時間大部分都在 2 秒以上,取平均值更是在 3 秒左右。[Google的報告](https://support.google.com/webmasters/answer/9205520?hl=zh-Hans)指出: * 如果網頁加載時間從 1 秒增加到 3 秒,跳出率就會提高**32%**。 * 如果網頁加載時間從 1 秒增加到 6 秒,跳出率就會上升**106%**。 ## 三、數據排查 &emsp;&emsp;在數據庫中,將指定的性能數據記錄導出到 Excel 中。 &emsp;&emsp;翻了一條后發現,性能問題集中在 DOM 中。 ~~~ { "unloadEventTime": 0, "loadEventTime": 1, "interactiveTime": 1255, "parseDomTime": 1075, "initDomTreeTime": 721, "readyStart": 5, "redirectCount": 0, "compression": 0, "redirectTime": 0, "appcacheTime": 0, "lookupDomainTime": 0, "connectSslTime": 0, "connectTime": 0, "requestTime": 119, "requestDocumentTime": 119, "responseDocumentTime": 0, "TTFB": 534, } ~~~ &emsp;&emsp;JSON 中的?interactiveTime、parseDomTime 和 initDomTreeTime 消耗的時間都不短,計算規則如下所示。 ~~~ /** * 解析 DOM 樹結構的時間 * 期間要加載內嵌資源 * 反省下你的 DOM 樹嵌套是不是太多了 */ api.parseDomTime = timing.domComplete - timing.domInteractive; /** * 請求完畢至DOM加載耗時 */ api.initDomTreeTime = timing.domInteractive - timing.responseEnd; /** * 首次可交互時間 */ api.interactiveTime = timing.domInteractive - timing.fetchStart; ~~~ &emsp;&emsp;參考 W3C 第二版性能參數圖可知,慢的地方集中在 Processing 階段。 :-: ![](https://img.kancloud.cn/e4/44/e4444c72fa8a5b8d5f523628b3280eef_1280x406.png =800x) ## 四、Chrome DevTools &emsp;&emsp;打開 Chrome DevTools 中的 Performance 一欄,錄制后,可在火焰圖中看到長任務。 &emsp;&emsp;點擊 Long task 鏈接,會跳轉到[使用 RAIL 模型衡量性能](https://web.dev/rail/)一文。 ![](https://img.kancloud.cn/87/94/87940d7c9125935708e9c69bf9cf2d6a_1930x1190.png =800x) &emsp;&emsp;在 PC 瀏覽器中打開肯定會比在手機中快,但即使如此,還是出現了性能瓶頸,說明這里是真的慢。 &emsp;&emsp;藍底的 DCL 是?[DOMContentLoaded](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/DOMContentLoaded_event)事件,在 HTML 文檔被完全加載和解析后觸發,綠底的 FP 就是白屏時間。 &emsp;&emsp;黃底的 Evaluate Script 表示加載 JavaScript 腳本,Compile Script 表示執行 JavaScript 腳本。 &emsp;&emsp;再來看看網絡請求瀑布圖,下圖中的藍線就是 DCL,可以清晰的看到,藍線之前在加載的基本都是 JavaScript 腳本。 :-: ![](https://img.kancloud.cn/9b/c7/9bc741d0abebcbac08224f21888c1587_1928x1058.png =800x) &emsp;&emsp;由此可知,加載的腳本有點多,并且有一個 chunk-vendors.js 腳本還比較大,下載時間有點長(依據藍色塊)。 ## 五、代碼分析 &emsp;&emsp;定位到了問題根源,那就直接查看基于 Vue 的代碼是怎么寫的了。 **1)HTML** &emsp;&emsp;下面是編譯后的頁面 HTML 結構,只列出了關鍵部分。 ~~~html <!DOCTYPE html> <html lang=en> <head> <script src=https://res.wx.qq.com/open/js/jweixin-1.6.0.js></script> <script src=//www.xxxx.com/flexible/flexible.js></script> <script src=//www.xxxx.co/files/js/baidu.js></script> <script src=//www.xxxx.co/files/js/shin.js></script> <link href=//www.xxxx.me/game/css/operation37.cba04f10.css rel=preload as=style> <link href=//www.xxxx.me/game/js/chunk-lodash.152ef24b.js rel=preload as=script> <link href=//www.xxxx.me/game/js/chunk-lottie.23b9982e.js rel=preload as=script> <link href=//www.xxxx.me/game/js/operation37.fa5f5378.js rel=preload as=script> <link href=//www.xxxx.me/game/css/chunk-vendors.779f7d1d.css rel=stylesheet> <link href=//www.xxxx.me/game/css/operation37.cba04f10.css rel=stylesheet> </head> <body> <div id=app></div> <script src=//www.xxxx.me/game/js/chunk-vendors.ca022e99.js></script> <script src=//www.xxxx.me/game/js/operation37.fa5f5378.js></script> </body> </html> ~~~ &emsp;&emsp;首先在 head 中,引入了大量的 JavaScript 腳本,flexible.js 其實在構建時可以內聯,不需要網絡訪問。 &emsp;&emsp;然后?jweixin-1.6.0.js 和 baidu.js 這兩個腳本完全可以延遲加載,后者就是增加百度統計的腳本。 &emsp;&emsp;接著就是 shin.js 需要做壓縮處理,可以減少 50% 以上的尺寸。 &emsp;&emsp;在 link 元素中,使用了[preload](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Link_types/preload),表示可并行的預加載,并且不會執行,這是提升頁面性能的一種手段。 &emsp;&emsp;雖然第三方的庫(chunk-vendors.ca022e99.js)和業務主邏輯(operation37.fa5f5378.js)兩個腳本聲明在 body 中。 &emsp;&emsp;但是主結構就是個空的 div,因此在加載和運行時就會延長 DOM 的解析,影響白屏時間。 **2)vendors 優化** &emsp;&emsp;Vue 內置了一條命令,可以查看每個腳本的尺寸以及內部依賴包的尺寸。 &emsp;&emsp;在下圖中,vendors.js 的原始尺寸是 3.76M,gzipped 壓縮后的尺寸是 442.02KB,比較大的包是 lottie、swiper、moment、lodash 等。 :-: ![](https://img.kancloud.cn/ee/0c/ee0cdbdec497af0f64215036f050adcc_3224x1835.png =800x) &emsp;&emsp;這類比較大的包可以再單獨剝離,不用全部聚合在 vendors.js 中。 &emsp;&emsp;在 vue.config.js 中,配置 config.optimization.splitChunks(),如下所示,參數含義可[參考官網](https://webpack.docschina.org/plugins/split-chunks-plugin)。 ~~~ config.optimization.splitChunks( { cacheGroups: { vendors: { name: 'chunk-vendors', test: /[\\/]node_modules[\\/]/, priority: -10, chunks: 'initial' }, lottie: { name: 'chunk-lottie', test: /[\\/]node_modules[\\/]lottie-web[\\/]/, chunks: 'all', priority: 3, reuseExistingChunk: true, enforce: true }, swiper: { name: 'chunk-swiper', test: /[\\/]node_modules[\\/]_swiper@3.4.2@swiper[\\/]/, chunks: 'all', priority: 3, reuseExistingChunk: true, enforce: true }, lodash: { name: 'chunk-lodash', test: /[\\/]node_modules[\\/]lodash[\\/]/, chunks: 'all', priority: 3, reuseExistingChunk: true, enforce: true } } } ) ~~~ &emsp;&emsp;在經過一頓初步操作后,原始尺寸降到 2.4M,gzipped 壓縮后的尺寸是 308.64KB,比之前少了 100 多 KB。 :-: ![](https://img.kancloud.cn/60/e2/60e2b9c4afbb83c585273aee6f9afd63_3224x1836.png =800x) &emsp;&emsp;現在在入口處需要單獨聲明依賴的包,否則不會自動引入。 ~~~ pages: { operation37: { entry: 'src/pages/operation37/index.js', template: 'src/pages/operation37/index.html', filename: 'operation37.html', title: '榜單配置頁面', chunks: ['chunk-lottie', 'operation37', 'chunk-vendors'] }, } ~~~ &emsp;&emsp;其實大部分的 H5 頁面都比較簡單,可能就使用了包的一個小功能,那完全可以自己用代碼實現,這樣就不必依賴那個大包了。 &emsp;&emsp;后面就是在代碼邏輯層面的優化,核心就是減少腳本尺寸。優化后,再去觀察數據的變化。 **3)CDN加速** &emsp;&emsp;之前部分靜態資源采取了 CDN 加速,現在需要將 game 下面中的靜態資源全部走 CDN。 &emsp;&emsp;在云端配置些參數,就能走 CDN。不過,第一次沒有配置好,沒有配置轉發路徑,造成了嚴重的線上問題。 &emsp;&emsp;第二次就比較謹慎,在測試環境將之前碰到的問題都驗證后,才最終在線上配置。 &emsp;&emsp;白屏時間占比變化: * 1 秒內的占比從 77.3% 最高提升至 78.7% * 1 - 2 秒占比從 15.6% 最高提升至 18.7% * 2 - 3 秒占比從 4% 最低下降至 1.8% * 3 - 4 秒占比從 1.1% 最低下降至 0.6% * 4 秒以上的占比從 2.1% 最低下降至 1.4% 參考資料: [長的 JavaScript 任務是否會延遲您的交互時間?](https://web.dev/i18n/zh/long-tasks-devtools/) [狙殺頁面卡頓 —— Performance 工具指北](https://zhuanlan.zhihu.com/p/41017888) [chrome performance看瀏覽器渲染過程](https://blog.csdn.net/It_rod/article/details/79661739) [深入理解瀏覽器解析渲染 HTML](https://juejin.cn/post/6844904131346300942) [Vue CLI 項目頁面打開時間優化:從16秒到2秒內](http://www.zuo11.com/blog/2020/11/vue_cli_slow.html) [preload 讓加載和解析解耦](https://juejin.cn/post/6844903854690009102) ***** > 原文出處: [博客園-Web優化躬行記](https://www.cnblogs.com/strick/category/1795726.html) [知乎專欄-Web優化躬行記](https://zhuanlan.zhihu.com/c_1260996761008627712) 已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎閱讀。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看