feat: Implement comprehensive Clerk ChunkLoadError recovery system
✨ Enhanced chunk error detection and automatic fallback to Supabase auth - Enhanced isClerkChunkError with specific CDN pattern matching (joint-cheetah-86.clerk.accounts.dev) - Added automatic Clerk disable when chunk loading fails - Implemented graceful fallback to Supabase authentication without interruption - Added user-friendly error messages and recovery UI - Created multi-layered error handling across ErrorBoundary, ClerkProvider, and global handlers - Added vite.config optimization for chunk loading with retry logic 🔧 Core improvements: - setupChunkErrorProtection() now activates immediately in main.tsx - Enhanced ClerkProvider with comprehensive error state handling - App.tsx ErrorBoundary detects and handles Clerk-specific chunk errors - Automatic sessionStorage flags for Clerk disable/skip functionality - URL parameter support for noClerk=true debugging 🚀 User experience: - Seamless transition from Clerk to Supabase when CDN fails - No app crashes or white screens during authentication failures - Automatic page refresh with fallback authentication system - Clear error messages explaining recovery process This resolves the ChunkLoadError: Loading chunk 344 failed from Clerk CDN and ensures the app remains functional with Supabase authentication fallback. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
65
src/App.tsx
65
src/App.tsx
@@ -27,7 +27,12 @@ import {
|
||||
createLazyComponent,
|
||||
resetChunkRetryFlags,
|
||||
} from "./utils/lazyWithRetry";
|
||||
import { setupChunkErrorProtection } from "./utils/chunkErrorProtection";
|
||||
import {
|
||||
setupChunkErrorProtection,
|
||||
isChunkLoadError,
|
||||
isClerkChunkError,
|
||||
handleChunkLoadError,
|
||||
} from "./utils/chunkErrorProtection";
|
||||
import {
|
||||
ClerkProvider,
|
||||
ClerkDebugInfo,
|
||||
@@ -111,13 +116,67 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
||||
logger.error("애플리케이션 오류:", error, errorInfo);
|
||||
// Sentry에 에러 리포팅
|
||||
|
||||
// ChunkLoadError 처리
|
||||
if (isChunkLoadError(error)) {
|
||||
if (isClerkChunkError(error)) {
|
||||
logger.warn("Error Boundary에서 Clerk 청크 오류 감지. 자동 복구 시도");
|
||||
// Clerk 자동 비활성화
|
||||
sessionStorage.setItem("disableClerk", "true");
|
||||
// 3초 후 새로고침
|
||||
setTimeout(() => {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set("noClerk", "true");
|
||||
url.searchParams.set("_t", Date.now().toString());
|
||||
window.location.href = url.toString();
|
||||
}, 3000);
|
||||
return;
|
||||
} else {
|
||||
// 일반 청크 오류 처리
|
||||
handleChunkLoadError(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Sentry에 에러 리포팅 (청크 오류가 아닌 경우만)
|
||||
captureError(error, { errorInfo });
|
||||
}
|
||||
|
||||
render(): ReactNode {
|
||||
if (this.state.hasError) {
|
||||
// 오류 발생 시 대체 UI 표시
|
||||
// ChunkLoadError인 경우 특별한 UI 표시
|
||||
if (this.state.error && isChunkLoadError(this.state.error)) {
|
||||
const isClerkError = isClerkChunkError(this.state.error);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen p-4 text-center">
|
||||
<div className={`text-4xl mb-4 ${isClerkError ? "🔧" : "⚠️"}`}>
|
||||
{isClerkError ? "🔧" : "⚠️"}
|
||||
</div>
|
||||
<h2 className="text-xl font-bold mb-4">
|
||||
{isClerkError ? "Clerk 로딩 오류" : "앱 로딩 오류"}
|
||||
</h2>
|
||||
<p className="mb-4 text-gray-600">
|
||||
{isClerkError
|
||||
? "Supabase 인증으로 자동 전환 중입니다. 잠시만 기다려주세요..."
|
||||
: "앱을 복구하고 있습니다. 잠시만 기다려주세요..."}
|
||||
</p>
|
||||
{!isClerkError && (
|
||||
<button
|
||||
onClick={() => {
|
||||
sessionStorage.clear();
|
||||
window.location.reload();
|
||||
}}
|
||||
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
|
||||
>
|
||||
수동 새로고침
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 일반 오류 처리
|
||||
return (
|
||||
this.props.fallback || (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen p-4 text-center">
|
||||
|
||||
Reference in New Issue
Block a user