The Complete Junior to Senior Web Developer Roadmap - Performance part2 隨意筆記

前言

這章節主要在講述 React Performance 的優化。

為何要 code splitting

如果不做 code splitting,就會直接載入 Webpack bundle 好的一大包檔案,這當然也是沒問題,但使用者就會因為下載這一大包檔案而在使用時卡住一陣子,影響使用者體驗。

code splitting 的用意就是在進入那個頁面,需要使用那個 Component 時才下載檔案,改善網頁讀取速度,增進使用體驗。

Code Splitting - React lazy

React 官方文件 - Code-Splitting

[译] 延迟加载 React Components (用 react.lazy 和 suspense)

React 官方提供 code splitting 的方法是 React.lazy,以下提供簡單的使用範例,可以到 這裡 clone 專案玩玩看

這邊課程提供的是一個自製的 router,在點擊按鈕的同時,就會切換到不同 route,return 相對應的 component,達到 code splitting 的效果。

首先要用 React.lazy 包裹著要 import 進來的檔案。

const Page2Lazy = React.lazy(() => import('./Components/Page2'))
const Page3Lazy = React.lazy(() => import('./Components/Page3'))

再來在相對應的 return Component 中,加入 Suspense 包裹住使用 React.lazy 的 Component。

render() {
    if (this.state.route === 'page1') {
      return <Page1 onRouteChange={this.onRouteChange} />
    } else if (this.state.route === 'page2') {
      return (
        <Suspense fallback={<div>Loading...</div>}>
          <Page2Lazy onRouteChange={this.onRouteChange} />
        </Suspense>
      )
    } else {
      return (
        <Suspense fallback={<div>Loading...</div>}>
          <Page3Lazy onRouteChange={this.onRouteChange} />
        </Suspense>
      )
    }
  }

lazy component 都必須包裹在 Suspense Component 裡面,Suspense 的用處在於可以在 fallback 這個 props 放入 loading 時要給予的 Component,以避免在 import 檔案時的空檔使用者會很疑惑,陷入等待空畫面的狀態。

當然,搭配 Router 也是可以的,就像下面這樣:

render() {
  return(
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/page1" component={Page1}/>
        <Route path="/page2" component={Page2Lazy}/>
        <Route path="/page2" component={Page3Lazy}/>
      </Switch>
    </Suspense>
  )
}

另外,關於 module 載入失敗的 error 也可以做相對應的處理,可以寫一個 ErrorBoundary 的 Component 來處理錯誤,更多詳情在 React 官方文件 - 錯誤邊界 可以參考。

使用的話就像這樣:

const MyComponent = () => (
  <div>
    <MyErrorBoundary>
      <Suspense fallback={<div>Loading...</div>}>
        <section>
          <OtherComponent />
          <AnotherComponent />
        </section>
      </Suspense>
    </MyErrorBoundary>
  </div>
);

SSR

值得注意的是,React.lazy 並不能用在 Server Side Rendering,所以如果要做 SSR 的話,可以改用另一個叫做 Loadable Components 的套件!

另外當然還有其他優化能做,比如 class component 裡的 shouldComponentUpdate,React Hooks 裡面的 useCallback 等等,課程裡面也有提及,但目前有點懶惰,先紀錄下 React lazy~