大家好,我卡頌。
昨天在開源圈發生個小插曲。起因是有個使用者表示:React
新文件在文件結構、美觀度、效能等各方面都達到很高的標準。
尤雨溪對Vue
新文件與React Beta
文件做了測試後表示:在效能這塊,Vue
新文件更具優勢。
Dan
表示:當前文件還處於Beta
版本,現在有更重要的工作要完成,正式版上線前會優化效能。
話雖這麼說,Dan
應該是通了個宵優化了一把效能:
本篇文章我們來看看,Dan
都做了哪些優化。
歡迎加入人類高質量前端框架群,帶飛
優化效果
經過優化後的lightHouse
跑分:
作為對照,Vue
文件的跑分:
兩者10次TTI跑分對比:
這裡的TTI(Time to Interactive,即可互動時間),衡量的是頁面變得完全可互動所需時間,其中完全可互動指:
- 頁面展示了有用資訊(由FCP衡量,FCP指First Contentful Paint)
- 可見頁面中大部分元素完成事件繫結,互動響應的延遲在50ms內
優化措施
優化主要有兩個思路:
- 編譯時:減少打包體積
- 執行時:非首屏必需程式碼延遲載入
編譯時優化
之前入口處全量引入了一個工具函式utils
,現在將其中方法拆分成不同檔案,這樣能減少首屏bundle
體積:
再比如:
這部分優化讓bundle
體積減少約一半:
其次,當前Next.js
(文件使用的框架)沒有預設開啟針對現代瀏覽器編譯。這意味著bundle
中會引入更多polyfill
,有更多語法轉換及幫助函式。
Dan
通過配置開啟了這個功能:
執行時優化
執行時優化的方式主要是:懶載入非必需資源。
新文件中存在很多codesandbox
(線上示例),這些示例依賴CodeMirror linter
,但這不是首屏必需的。
所以Dan
將這部分資源懶載入:
除此之外,如果你細心觀察會發現,Total Blocking Time
指標下降很多:
TBT(Total Blocking Time
,即總阻塞時間)測量頁面First Contentful Paint 首次內容繪製 (FCP)與Time to Interactive 可互動時間 (TTI)之間的總時間。。
一般來說,如果JS
執行時間過長,就會影響這個指標。
我們知道,頁面載入後前端框架會有首屏渲染
的初始化過程。即使是服務端渲染,也會有Hydrate
(注水)的過程。
而React18
的Selective Hydration
為解決這一問題提供了好方法。
如果你的React18
應用是SSR
,那麼被<Suspense/>
包裹的元件部分不會參與首次Hydrate
的過程。
也就是說,被<Suspense/>
包裹的部分不會影響阻塞時間。
所以,雖然這部分工作很重要,但Dan
需要做的,僅僅是把一些對首屏顯示不太重要的元件包裹在<Suspense/>
中。
可以看到,在將一些元件用<Suspense/>
包裹前Hydrate
作為一個長任務的耗時:
當包裹之後,這個長任務持續時間顯著降低,進而降低TBT
:
總結
這些只是初步的優化結果,後續還有很多優化工作值得去做。比如INP(Interaction to Next Paint,與下一次Paint的互動)指標還是偏高:
Dan
坦言:指標偏高的原因可能是因為 —— React
本身比較慢。
他對此提出了一些猜想,你可以到這裡參與討論。