F: Improve dynamic loading error handling

This commit is contained in:
Ivan 2025-11-09 16:04:16 +03:00
parent 9c474a26d1
commit 0a34a5ab84
3 changed files with 51 additions and 7 deletions

View File

@ -1,17 +1,36 @@
'use client';
import { useEffect } from 'react';
import { useNavigate, useRouteError } from 'react-router';
import { Button } from '@/components/control';
import { InfoError } from '@/components/info-error';
import { isStaleBundleError } from '@/utils/utils';
export function ErrorFallback() {
const error = useRouteError();
const router = useNavigate();
useEffect(() => {
if (isStaleBundleError(error)) {
console.warn('Detected stale bundle — reloading...');
window.location.reload();
}
}, [error]);
function resetErrorBoundary() {
Promise.resolve(router('/')).catch(console.error);
}
if (isStaleBundleError(error)) {
return (
<div className='flex flex-col gap-3 my-3 items-center antialiased' role='alert'>
<h1 className='my-2'>Обновление страницы...</h1>
<p>Обнаружена устаревшая версия приложения. Перезагрузка страницы...</p>
</div>
);
}
return (
<div className='flex flex-col gap-3 my-3 items-center antialiased' role='alert'>
<h1 className='my-2'>Что-то пошло не так!</h1>

View File

@ -14,15 +14,27 @@ if (typeof window !== 'undefined' && import.meta.env.DEV) {
}
if (typeof window !== 'undefined') {
window.addEventListener('error', (event: ErrorEvent) => {
const error = event.error as Error;
if (
error instanceof Error &&
typeof error.message === 'string' &&
error.message.includes('Failed to fetch dynamically imported module')
) {
function handleStaleBundleError(error: unknown): boolean {
if (error instanceof Error && error.message.includes('Failed to fetch dynamically imported module')) {
console.warn('Detected stale bundle — reloading...');
window.location.reload();
return true;
}
if (typeof error === 'string' && error.includes('Failed to fetch dynamically imported module')) {
console.warn('Detected stale bundle — reloading...');
window.location.reload();
return true;
}
return false;
}
window.addEventListener('error', (event: ErrorEvent) => {
handleStaleBundleError(event.error);
});
window.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => {
if (handleStaleBundleError(event.reason)) {
event.preventDefault();
}
});
}

View File

@ -8,6 +8,19 @@ import { type AxiosError, type AxiosHeaderValue, type AxiosResponse, isAxiosErro
import { PARAMETER } from './constants';
import { infoMsg, promptText } from './labels';
/**
* Check if error is stale bundle error.
*/
export function isStaleBundleError(error: unknown): boolean {
if (error instanceof Error) {
return error.message.includes('Failed to fetch dynamically imported module');
}
if (typeof error === 'string') {
return error.includes('Failed to fetch dynamically imported module');
}
return false;
}
/**
* Wrapper class for generalized text matching.
*