做者:Jogis
原文連接:https://github.com/yesvods/Bl...
轉載請註明原文連接以及做者信息html
前端框架時代,爲開發體驗、效率與頁面性能帶來,很是大的革命。你們紛紛拿起一系列打包工具(webpack/parcel etc.),配合一系列加載器快速搭建起一個 SPA 頁面。前端
SPA 應用帶來的好處很是明顯;react
可是也帶來一系列性能問題:webpack
這些問題是使用 SPA 模式不可避免的,經過了解 SPA 加載運行過程,能夠逐漸看清楚引發性能問題的根本緣由,經過精細化應用加載,來解決這些問題。git
比起通常的簡單頁面,SPA 最大的問題,就是在初始化之時引入大量框架方案腳本,這致使腳本體積隨着項目發展體積愈發增大。github
不少人會關注腳本的加載體積,經過一系列方案來提高緩存命中率,減小腳本請求次數。在網絡環境較差的移動端,儘可能減小請求時間意義很大。web
但這不是銀彈,移動設備對腳本的解析、編譯、執行性能較差(腳本加載參考《圖說舌尖上的腳本》),即使能夠徹底利用緩存,執行時間也是性能一大瓶頸。後端
性能優化原則:貧則獨善其身,富則兼濟天下。緩存
隨着項目不斷髮展,頁面不斷增長,源源不斷的第三方組件&工具庫加入到Bundle
裏面,良好的 SPA 架構能夠保證大型 SPA 項目依舊保持極致的性能與體驗。下面介紹一個優秀性能&體驗 SPA 具有的特性:性能優化
快速啓動應用,並行發起 Bundle 加載&拉取初始數據。相信你們已經發現了,SPA 初始化時候,不得不等待 bundle 返回並執行後,纔會發起數據加載。
因爲在移動設備上(即使有緩存)bundle 加載極爲耗時,咱們能夠充分利用這段時間將數據進行預加載。這項特性,使得後面的優化起到更加明顯的效果。
以下示例代碼:
// app.js Promise.all([load('bundle'), load('data')])
利用異步加載方式,在路由註冊時提供異步拉取組件的方法,僅在須要進入對應路由時,對應組件纔會被加載進來。
route({ Home: () => import('@/coms/home'), About: () => import('@/coms/about') })
在Home
和About
等路由裏面,可能公用一套 UI 組件,若不將異步加載公用組件統一打包,每次加載 路由時,都會額外加載一套 UI 組件。經過將公用組件提取打包成Vendor
,能夠減小下次進入路由加載體積與時間。
BTW:在webpack < 4
時,依舊須要手動維護異步加載組件公用組件。webpack4
提供更豐富的異步組件抽離方案。
當首屏加載完畢後,設備&網絡處於空閒狀態,能夠對其餘路由組件進行預加載,以便提高頁面切換性能。
預加載是一個很是繁瑣的過程,咱們能夠設計一個極小啓動器,在頁面渲染後快速預加載後續組件:
// 全部包含Page的路由組件均會被預加載 boostraper.loadMatch('Page')
webpack4
在 ESM tree shaking
上作了極大優化,使得在引用工具庫時候真正作到"按需打包",這要求不管是本身開發的工具庫,抑或使用第三方工具庫,打包&使用 ESM 版本很是必要。
根據 PWA 緩存策略,能夠將訪問的頁面index.html
緩存起來,下次打開時候優先利用緩存,再發起請求更新緩存。這使得 SPA 應用幾乎不須要額外時間即可加載應用首屏文檔流。
Skeleton Page
SPA 首屏加載面臨較長時間白屏,骨架圖是一個完美的"緩兵之計"。在谷歌研究員的文章 中有提到,骨架圖對用戶體驗有極大的提高:
快速展現
穩定加載
須要注意的是,骨架圖應儘可能保持足夠小巧與簡單,以確保不會嚴重影響頁面後續加載。
不管如何優化性能加載,在頁面切換時候依舊須要獲取頁面數據,若處理很差,可能會在數據返回前有短暫的不友好"空白"。經過如下方式能夠很好處理這個問題:
友好的切換前 Loading
轉場動畫
除了上述提到的 SPA 優化方案,Web 性能基礎也是必備的基石(如域名收斂、合理文檔結構)。性能優化本質是一個頁面精細化監控運營的過程,也要求咱們對 Web 加載的過程與邏輯有更多的思考與理解。