React(19) - ErrorBoundary


Posted by TempuraEngineer on 2024-04-12

目錄


ErrorBoundary是甚麼


以React撰寫的網頁在渲染時出錯的話(就像上圖的throw Error),React會把整個UI畫面都移除掉,為了避免這個慘況就需要使用ErrorBoundary

它會包裹住部分組件,讓被包裹的組件在渲染出錯時不顯示error message,而改成顯示fallback UI的組件

另外需要注意ErrorBoundary只能用class component的形式撰寫

且需要在getDerivedStateFromError 這個生命週期更新state才能成功渲染fallback UI,反之如果只是要再捕捉到錯誤後做某些事的話只要用componentDidCatch即可


奇怪的chunk error

之前遇到了一個奇怪的狀況是每當網頁剛deploy到各個環境上就有機會會在某幾個頁面出現chunk error(客戶端試圖request chunk file卻找不到),但重新整理後又正常了,且恢復正常後到下次deploy前都不會再跳出chunk error

chunk error指的是載入chunk的找不到chunk,看解法前先來瞭解一下甚麼是chunk、code splitting


chunk & code splitting是甚麼

以前端框架撰寫網頁的時候,會需要bundlers (ex:webpack, gulp, grunt, vite) 幫我們打包網站,而code splitting就是其中一件bundler會處理的事

code splitting指的是將程式碼分割成多個小小的 chunk,需要時(進到對應的頁面時)才去下載,藉此提升網站的 initial load performance

隨著你的網站越來越複雜,CSS 和 JS 檔案的大小也會越來越大為了避免一次下載所有檔案,導致網頁載入速度過慢,所以才需要code splitting

Webpack會幫你把chunk file的檔名取成contenthash的形式,每當頁面(或是asset)的內容變動contenthash也會變

在上一段提到chunk error通常出現在發完新版本的時候,而新版本內一定會有內容的變動,加上瀏覽器會試著從快取找資源(舊的chunk),所以才會出錯


現況 & 沒用的方法

接著回到chunk error

在next.js的PR區有人嘗試修正next.js不能設定headers這個問題了,只是直到目前(2024年4月)都沒有人review,所以PR遲遲沒被merge

fix: allow next.config.js overwrite cache-control header

在PR被merge前,只好試試其他方法了😢

以下先列出幾個曾經試過的沒用方法


沒用的方法

  • next.config.js加Cache-Control headers

    你可能會查到有人說可以透過在next.config.js加上Cache-Control headers解決,不過我實際試過並沒有效果

    You cannot set Cache-Control headers in next.config.js for pages or assets, as these headers will be overwritten in production to ensure that responses and static assets are cached effectively.

    官方文件有說「為了確保靜態資源(static asset)被有效率地快取住,所以在production環境下next.config.js內的設定會被覆蓋掉」,也就是說即便設定了Cache-Control headers仍會失效


用ErrorBoundary繞過去

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidCatch(error, errorInfo) {
    if(error.name === 'ChunkError') {
      // 如果捕捉到chunk error就重整
      window.location.reload();
    }
  }

  render() {
    return this.props.children; 
  }
}
<ErrorBoundary>
   // 這裡放會出chunk error的組件 (ex: 頁面組件)
   <Outlet />
</ErrorBoundary>


參考資料

Catching rendering errors with an error boundary
Complete Guide on React Error Boundary

Dynamic Import, Code Splitting, Lazy Loading, and Error Boundaries
React | 為太龐大的程式碼做 Lazy Loading 和 Code Splitting
鐵人賽 Day05 - React 中的 Code splitting(代碼分離)方法
Unveiling the Power of Code-Splitting with Webpack for React and Redux Applications

Cache-Control headers set in next.config.js are overwritten
How to fix ChunkLoadError in your ReactJS application










Related Posts

【Day07】總複習!摻在一起做成...

【Day07】總複習!摻在一起做成...

Spring boot系列(六)Log

Spring boot系列(六)Log

【單元測試的藝術】Chap 1: 單元測試基礎

【單元測試的藝術】Chap 1: 單元測試基礎


Comments