From 1279a33259a967b731605046fcbc1dfed9c0a835 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Tue, 6 Apr 2021 15:23:52 +0200 Subject: [PATCH] Handle chunk loading errors Signed-off-by: Oliver Sand --- .changeset/forty-queens-hear.md | 7 +++ packages/core-api/src/app/types.ts | 2 +- .../core-api/src/extensions/extensions.tsx | 56 +++++++++++-------- packages/core/src/api-wrappers/createApp.tsx | 34 ++++++++--- 4 files changed, 67 insertions(+), 32 deletions(-) create mode 100644 .changeset/forty-queens-hear.md diff --git a/.changeset/forty-queens-hear.md b/.changeset/forty-queens-hear.md new file mode 100644 index 0000000000..5e0b35162a --- /dev/null +++ b/.changeset/forty-queens-hear.md @@ -0,0 +1,7 @@ +--- +'@backstage/core': patch +'@backstage/core-api': patch +--- + +Introduce a `load-chunk` step in the `BootErrorPage` to show make chunk loading +errors visible to the user. diff --git a/packages/core-api/src/app/types.ts b/packages/core-api/src/app/types.ts index 5bdf51837d..cf3aaac931 100644 --- a/packages/core-api/src/app/types.ts +++ b/packages/core-api/src/app/types.ts @@ -24,7 +24,7 @@ import { AppConfig } from '@backstage/config'; import { SubRouteRef } from '../routing/types'; export type BootErrorPageProps = { - step: 'load-config'; + step: 'load-config' | 'load-chunk'; error: Error; }; diff --git a/packages/core-api/src/extensions/extensions.tsx b/packages/core-api/src/extensions/extensions.tsx index 9463e437e3..8ff4055e61 100644 --- a/packages/core-api/src/extensions/extensions.tsx +++ b/packages/core-api/src/extensions/extensions.tsx @@ -15,9 +15,10 @@ */ import React, { lazy, Suspense } from 'react'; +import { useApp } from '../app'; +import { BackstagePlugin, Extension } from '../plugin/types'; import { RouteRef, useRouteRef } from '../routing'; import { attachComponentData } from './componentData'; -import { Extension, BackstagePlugin } from '../plugin/types'; type ComponentLoader = | { @@ -40,30 +41,41 @@ export function createRoutableExtension< return createReactExtension({ component: { lazy: () => - component().then(InnerComponent => { - const RoutableExtensionWrapper: any = (props: any) => { - // Validate that the routing is wired up correctly in the App.tsx - try { - useRouteRef(mountPoint); - } catch { - throw new Error( - `Routable extension component with mount point ${mountPoint} was not discovered in the app element tree. ` + - 'Routable extension components may not be rendered by other components and must be ' + - 'directly available as an element within the App provider component.', - ); - } - return ; - }; + component().then( + InnerComponent => { + const RoutableExtensionWrapper: any = (props: any) => { + // Validate that the routing is wired up correctly in the App.tsx + try { + useRouteRef(mountPoint); + } catch { + throw new Error( + `Routable extension component with mount point ${mountPoint} was not discovered in the app element tree. ` + + 'Routable extension components may not be rendered by other components and must be ' + + 'directly available as an element within the App provider component.', + ); + } + return ; + }; - const componentName = - (InnerComponent as { displayName?: string }).displayName || - InnerComponent.name || - 'LazyComponent'; + const componentName = + (InnerComponent as { displayName?: string }).displayName || + InnerComponent.name || + 'LazyComponent'; - RoutableExtensionWrapper.displayName = `RoutableExtension(${componentName})`; + RoutableExtensionWrapper.displayName = `RoutableExtension(${componentName})`; - return RoutableExtensionWrapper as T; - }), + return RoutableExtensionWrapper as T; + }, + error => { + const RoutableExtensionWrapper: any = (_: any) => { + const app = useApp(); + const { BootErrorPage } = app.getComponents(); + + return ; + }; + return RoutableExtensionWrapper; + }, + ), }, data: { 'core.mountPoint': mountPoint, diff --git a/packages/core/src/api-wrappers/createApp.tsx b/packages/core/src/api-wrappers/createApp.tsx index db8d0d0636..b071c2d014 100644 --- a/packages/core/src/api-wrappers/createApp.tsx +++ b/packages/core/src/api-wrappers/createApp.tsx @@ -97,16 +97,32 @@ export function createApp(options?: AppOptions) { ); const DefaultBootErrorPage = ({ step, error }: BootErrorPageProps) => { - let message = ''; - if (step === 'load-config') { - message = `The configuration failed to load, someone should have a look at this error: ${error.message}`; + switch (step) { + case 'load-config': + // TODO: figure out a nicer way to handle routing on the error page, when it can be done. + return ( + + + + ); + case 'load-chunk': + return ( + + ); + default: + // TODO: figure out a nicer way to handle routing on the error page, when it can be done. + return ( + + + + ); } - // TODO: figure out a nicer way to handle routing on the error page, when it can be done. - return ( - - - - ); }; const apis = options?.apis ?? [];