perf(webui): lazily load module descriptors

This commit is contained in:
2026-07-30 04:35:57 +02:00
parent 9e219bc4d3
commit 47e106684d
14 changed files with 604 additions and 84 deletions
@@ -0,0 +1,76 @@
import { Component, Suspense, type ErrorInfo, type ReactNode } from "react";
import Button from "./Button";
import DismissibleAlert from "./DismissibleAlert";
import LoadingIndicator from "./LoadingIndicator";
type ModuleLoadBoundaryProps = {
children: ReactNode;
resetKey: string;
loading?: boolean;
};
type ModuleLoadBoundaryState = {
error: Error | null;
};
export default class ModuleLoadBoundary extends Component<
ModuleLoadBoundaryProps,
ModuleLoadBoundaryState
> {
state: ModuleLoadBoundaryState = { error: null };
static getDerivedStateFromError(error: Error): ModuleLoadBoundaryState {
return { error };
}
componentDidCatch(error: Error, info: ErrorInfo) {
console.error("GovOPlaN module route failed to load", error, info);
}
componentDidUpdate(previousProps: ModuleLoadBoundaryProps) {
if (
previousProps.resetKey !== this.props.resetKey &&
this.state.error
) {
this.setState({ error: null });
}
}
render() {
if (this.props.loading) {
return <ModuleLoadProgress />;
}
if (this.state.error) {
return (
<div className="content-pad module-load-error">
<DismissibleAlert tone="danger" dismissible={false}>
<p>i18n:govoplan-core.the_resource_could_not_be_loaded.0d1b6cbf</p>
<Button type="button" onClick={() => window.location.reload()}>
i18n:govoplan-core.reload.cce71553
</Button>
</DismissibleAlert>
</div>
);
}
return (
<Suspense
fallback={<ModuleLoadProgress />}
>
{this.props.children}
</Suspense>
);
}
}
function ModuleLoadProgress() {
return (
<div className="content-pad module-load-progress">
<LoadingIndicator
label="i18n:govoplan-core.loading_module.50161f3c"
size="md"
/>
<span>i18n:govoplan-core.loading_module.50161f3c</span>
</div>
);
}