import { Component, type ErrorInfo, type ReactNode, } from "react"; type RecoveryResult = | Readonly<{ action: "reload-once"; releasePair: string }> | Readonly<{ action: "support"; reason: string }>; type Props = Readonly<{ children: ReactNode; chunkId: string; recover(input: Readonly<{ chunkId: string; failureKind: "CHUNK_LOAD_FAILURE"; }>): Promise; }>; type State = Readonly<{ error: unknown | null; recovery: "idle" | "checking" | "reload-requested" | "support"; reason?: string; }>; export function isChunkLoadFailure(error: unknown): boolean { if (!(error instanceof Error)) return false; const value = `${error.name} ${error.message}`.toLowerCase(); return ( value.includes("chunkloaderror") || value.includes("loading chunk") || value.includes("dynamically imported module") || value.includes("failed to fetch module script") ); } export class ChunkRecoveryBoundary extends Component { state: State = { error: null, recovery: "idle" }; static getDerivedStateFromError(error: unknown): State { return { error, recovery: "checking" }; } componentDidCatch(error: unknown, _info: ErrorInfo) { if (!isChunkLoadFailure(error)) return; void this.props .recover({ chunkId: this.props.chunkId, failureKind: "CHUNK_LOAD_FAILURE", }) .then((result) => { this.setState({ error, recovery: result.action === "reload-once" ? "reload-requested" : "support", ...(result.action === "support" ? { reason: result.reason } : {}), }); }) .catch(() => { this.setState({ error, recovery: "support", reason: "recovery-controller-failed", }); }); } render() { const { error, recovery, reason } = this.state; if (error && !isChunkLoadFailure(error)) throw error; if (error && recovery === "checking") { return (
새 릴리스 정보를 확인하고 있습니다.
); } if (error && recovery === "reload-requested") { return (
새 버전으로 한 번만 전환합니다.
); } if (error && recovery === "support") { return (

화면 자산을 복구하지 못했습니다.

문제가 계속되면 배포 상태와 지원 참조 정보를 확인해 주세요.

); } return this.props.children; } }