目錄
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


