被diss效能差,Dan連夜優化React新文件

卡頌發表於2022-05-28

大家好,我卡頌。

昨天在開源圈發生個小插曲。起因是有個使用者表示:React新文件在文件結構、美觀度、效能等各方面都達到很高的標準。

尤雨溪對Vue新文件與React Beta文件做了測試後表示:在效能這塊,Vue新文件更具優勢。

左Vue,右React

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指標下降很多:

左之前,右之後

TBTTotal Blocking Time,即總阻塞時間)測量頁面First Contentful Paint 首次內容繪製 (FCP)Time to Interactive 可互動時間 (TTI)之間的總時間。。

一般來說,如果JS執行時間過長,就會影響這個指標。

我們知道,頁面載入後前端框架會有首屏渲染的初始化過程。即使是服務端渲染,也會有Hydrate(注水)的過程。

React18Selective Hydration為解決這一問題提供了好方法。

如果你的React18應用是SSR,那麼被<Suspense/>包裹的元件部分不會參與首次Hydrate的過程。

也就是說,被<Suspense/>包裹的部分不會影響阻塞時間。

所以,雖然這部分工作很重要,但Dan需要做的,僅僅是把一些對首屏顯示不太重要的元件包裹在<Suspense/>中。

可以看到,在將一些元件用<Suspense/>包裹前Hydrate作為一個長任務的耗時:

當包裹之後,這個長任務持續時間顯著降低,進而降低TBT

總結

這些只是初步的優化結果,後續還有很多優化工作值得去做。比如INP(Interaction to Next Paint,與下一次Paint的互動)指標還是偏高:

Dan坦言:指標偏高的原因可能是因為 —— React本身比較慢。

他對此提出了一些猜想,你可以到這裡參與討論

相關文章