diff --git a/airflow-core/src/airflow/ui/src/pages/ExternalView.tsx b/airflow-core/src/airflow/ui/src/pages/ExternalView.tsx index a1c80cdf2f37c..c74d9b25a4be3 100644 --- a/airflow-core/src/airflow/ui/src/pages/ExternalView.tsx +++ b/airflow-core/src/airflow/ui/src/pages/ExternalView.tsx @@ -18,7 +18,7 @@ */ import { Box } from "@chakra-ui/react"; import { useTranslation } from "react-i18next"; -import { useParams } from "react-router-dom"; +import { useLocation, useParams } from "react-router-dom"; import { usePluginServiceGetPlugins } from "openapi/queries"; import { ProgressBar } from "src/components/ui"; @@ -32,6 +32,8 @@ export const ExternalView = () => { const { page } = useParams(); const { data: pluginData, isLoading } = usePluginServiceGetPlugins(); + const { pathname } = useLocation(); + const externalView = page === "legacy-fab-views" ? { @@ -82,7 +84,7 @@ export const ExternalView = () => { m={-2} // Compensate for parent padding minHeight={0} > - + ); } diff --git a/airflow-core/src/airflow/ui/src/pages/ReactPlugin.tsx b/airflow-core/src/airflow/ui/src/pages/ReactPlugin.tsx index 9f43f72d90d8d..c530409a0e512 100644 --- a/airflow-core/src/airflow/ui/src/pages/ReactPlugin.tsx +++ b/airflow-core/src/airflow/ui/src/pages/ReactPlugin.tsx @@ -59,19 +59,29 @@ const loadPlugin = (reactApp: ReactAppResponse): Promise<{ default: PluginCompon // eslint-disable-next-line no-console console.error("Component failed to load:", error); - return { - default: ErrorPage, - }; + return { default: ErrorPage }; }); export const ReactPlugin = ({ reactApp }: { readonly reactApp: ReactAppResponse }) => { const { dagId, mapIndex, runId, taskId } = useParams(); - const Plugin = lazy(() => loadPlugin(reactApp)); + // If the plugin component was already registered on the global object by a previous load, + // render it directly without going through Suspense/lazy (avoids flashing the spinner). + const existing = (globalThis as Record)[reactApp.name]; + + if (typeof existing === "function") { + const Plugin = existing as PluginComponentType; + + return ; + } + + // Otherwise, lazy-load the bundle once. When it resolves, it must set a function component + // under globalThis[reactApp.name], which we then use as the default export. + const LazyPlugin = lazy(() => loadPlugin(reactApp)); return ( }> - + ); };