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