perf(ui): lazy load glossary customization views#29180
Conversation
| patchGlossaryTerm, | ||
| } from '../../rest/glossaryAPI'; | ||
| import { getEntityDeleteMessage } from '../../utils/EntityDisplayUtils'; | ||
| import { getEntityDeleteMessage } from '../../utils/EntityDisplayPureUtils'; |
There was a problem hiding this comment.
🚨 Bug: Imports reference non-existent util modules (build break)
This PR repoints several imports to module files that do not exist anywhere in the repository, which will fail TypeScript/bundler resolution and break the build:
-
EntityDisplayPureUtils— does not exist. Onlysrc/utils/EntityDisplayUtils.tsxexists, which is wheregetCountBadge,getEntityDeleteMessage, andgetEntityMissingErrorare actually exported.components/Glossary/GlossaryV1.component.tsx:import { getEntityDeleteMessage } from '../../utils/EntityDisplayPureUtils'components/Glossary/GlossaryHeader/GlossaryHeader.component.tsx:import { getEntityDeleteMessage } from '../../../utils/EntityDisplayPureUtils'pages/Glossary/GlossaryPage/GlossaryPage.component.tsx:import { getEntityMissingError } from '../../../utils/EntityDisplayPureUtils'utils/Glossary/GlossaryTermUtils.tsx:import { getCountBadge } from '../../utils/EntityDisplayPureUtils'
-
TaskNavigationUtils— does not exist.isTaskPendingFurtherApprovalis exported fromsrc/utils/TasksUtils.ts.components/Glossary/GlossaryTermTab/GlossaryTermTab.component.tsx:import { isTaskPendingFurtherApproval } from '../../../utils/TaskNavigationUtils'
These 'Pure' modules appear to belong to a sibling branch in the dashboard-LCP stack that has not landed on this branch (HEAD d86fd80 sits directly on main). Either create/extract the EntityDisplayPureUtils and TaskNavigationUtils modules (with the referenced exports) in this PR, or revert these imports back to their existing sources (EntityDisplayUtils and TasksUtils).
Revert imports to the modules that actually export these symbols.:
// GlossaryV1.component.tsx & GlossaryHeader.component.tsx
import { getEntityDeleteMessage } from '../../utils/EntityDisplayUtils';
// GlossaryPage.component.tsx
import { getEntityMissingError } from '../../../utils/EntityDisplayUtils';
// Glossary/GlossaryTermUtils.tsx
import { getCountBadge } from '../../utils/EntityDisplayUtils';
// GlossaryTermTab.component.tsx
import { isTaskPendingFurtherApproval } from '../../../utils/TasksUtils';
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
Code Review 🚫 Blocked 0 resolved / 1 findingsLazy loads glossary customization views to improve dashboard performance, but the changes are blocked because they reference non-existent utility modules, causing build failures. 🚨 Bug: Imports reference non-existent util modules (build break)📄 openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryV1.component.tsx:40 📄 openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.component.tsx:59 📄 openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx:66 📄 openmetadata-ui/src/main/resources/ui/src/utils/Glossary/GlossaryTermUtils.tsx:23 📄 openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryTermTab/GlossaryTermTab.component.tsx:106 This PR repoints several imports to module files that do not exist anywhere in the repository, which will fail TypeScript/bundler resolution and break the build:
These 'Pure' modules appear to belong to a sibling branch in the dashboard-LCP stack that has not landed on this branch (HEAD d86fd80 sits directly on main). Either create/extract the Revert imports to the modules that actually export these symbols.🤖 Prompt for agentsOptionsDisplay: compact → Showing less information. Comment with these commands to change:
Was this helpful? React with 👍 / 👎 | Gitar |
| export * from './GlossaryTermReferenceUtils'; | ||
| export * from './GlossaryTermWidgetUtils'; |
There was a problem hiding this comment.
Barrel re-export pulls widget deps into reference-only consumers
The export * from './GlossaryTermWidgetUtils' line means any module that imports only reference utilities through this barrel (e.g. createGlossaryTermEntityLink) will also evaluate GlossaryTermWidgetUtils, statically bundling useGenericContext, EntityType, and the ten lazy wrapper declarations. The lazy wrappers keep the heavy component implementations out of the bundle, but the widget utils module itself is always included. Since the motivation for splitting was to reduce what reference-only consumers pull in, callers that still use this barrel path don't fully benefit. Key consumers (WorkflowHistory, GlossaryTermSelectableList, CustomizeGlossaryTermBaseClass) have already been updated to the direct paths — consider updating any remaining barrel consumers and adding a deprecation notice here to prevent future drift.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| ) | ||
| ); | ||
|
|
||
| const TabsLabel = withSuspenseFallback( | ||
| lazy(() => import('../../common/TabsLabel/TabsLabel.component')) | ||
| ); | ||
|
|
||
| const GenericTab = withSuspenseFallback( | ||
| lazy(() => | ||
| import('../../Customization/GenericTab/GenericTab').then((module) => ({ | ||
| default: module.GenericTab, | ||
| })) | ||
| ) | ||
| ); | ||
|
|
||
| const OntologyExplorer = withSuspenseFallback( | ||
| lazy(() => import('../../OntologyExplorer/OntologyExplorer')) |
There was a problem hiding this comment.
Full-screen
<Loader /> fallback for small inline components
TabsLabel and AlignRightIconButton are tiny inline elements used as tab labels and an icon button. withSuspenseFallback wraps each with a Suspense boundary whose fallback is <div className="ant-layout-content flex-center"><Loader /></div> — a full-height, full-width centered spinner. On first load, the tab bar will momentarily render a full-screen loader in place of each tab label, causing a visible layout shift. Large route-level components like GlossaryHeader and OntologyExplorer are appropriate targets for this fallback, but for small inline components a lightweight inline placeholder (e.g. an empty <span> or null) avoids the jarring flash.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary
Testing
Ref: https://github.com/open-metadata/openmetadata-collate/issues/4230
Greptile Summary
This PR extracts glossary widget utilities into two focused files (
GlossaryTermReferenceUtils,GlossaryTermWidgetUtils) and converts statically-imported heavy components across the glossary feature tree to lazywithSuspenseFallbackwrappers, reducing initial bundle size and deferring LCP-blocking modules.GlossaryTermUtil.tsxis now a thin barrel;GlossaryTermReferenceUtilsholds pure reference helpers, andGlossaryTermWidgetUtilsholds the widget factory with all component imports deferred vialazy(). Key consumers are updated to direct import paths.GlossaryHeader,ActivityFeedTab,GenericTab,OntologyExplorer,ResizablePanels,AssetsTabs,GlossaryTermTab, and several smaller components inGlossaryDetails,GlossaryTermsV1, andGlossaryTermUtilsare all converted to dynamic imports wrapped withwithSuspenseFallback.getEntityDeleteMessage/getEntityMissingErrorupdated toEntityDisplayPureUtils,isTaskPendingFurtherApprovalmoved toTaskNavigationUtils, andcreateGlossaryTermEntityLinktoGlossaryTermReferenceUtils— all consistent with the project's pure-utils extraction pattern.Confidence Score: 4/5
Safe to merge with two minor UX/architecture observations addressed; no functional regressions introduced.
The lazy-loading conversion is mechanical and consistent. The two concerns are: withSuspenseFallback's full-screen loader fallback applied to small inline components (TabsLabel, AlignRightIconButton) which may cause a noticeable layout shift on first paint; and the barrel re-export in GlossaryTermUtil still bundling widget-util module code for reference-only consumers. Neither is a runtime bug, but the first affects perceived performance — the opposite of the stated goal for these small components.
GlossaryDetails.component.tsx (TabsLabel/AlignRightIconButton lazy fallback weight) and GlossaryTermUtil.tsx (barrel re-export scope)
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[GlossaryTermUtil.tsx\nbarrel re-export] --> B[GlossaryTermReferenceUtils.tsx\ncreateGlossaryTermEntityLink\nGlossaryTermListItemRenderer\nconvert helpers] A --> C[GlossaryTermWidgetUtils.tsx\ngetGlossaryTermWidgetFromKey\nlazy: WorkflowHistory\nlazy: RelatedTerms\nlazy: GlossaryTermSynonyms\nlazy: OwnerLabelV2, etc.] D[GlossaryTermSelectableList] -->|direct import| B E[WorkflowHistory.component] -->|direct import| B F[CustomizeGlossaryTermBaseClass] -->|direct import| C G[GlossaryDetails.component\nlazy: GlossaryHeader\nlazy: ActivityFeedTab\nlazy: TabsLabel\nlazy: GenericTab\nlazy: OntologyExplorer\nlazy: AlignRightIconButton] H[GlossaryTermsV1.component\nlazy: GlossaryHeader] I[GlossaryTermUtils.tsx\nlazy: TabsLabel\nlazy: ActivityFeedTab\nlazy: GenericTab\nlazy: AssetsTabs\nlazy: GlossaryTermTab\nlazy: OntologyExplorer\nlazy: ResizablePanels]%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% flowchart TD A[GlossaryTermUtil.tsx\nbarrel re-export] --> B[GlossaryTermReferenceUtils.tsx\ncreateGlossaryTermEntityLink\nGlossaryTermListItemRenderer\nconvert helpers] A --> C[GlossaryTermWidgetUtils.tsx\ngetGlossaryTermWidgetFromKey\nlazy: WorkflowHistory\nlazy: RelatedTerms\nlazy: GlossaryTermSynonyms\nlazy: OwnerLabelV2, etc.] D[GlossaryTermSelectableList] -->|direct import| B E[WorkflowHistory.component] -->|direct import| B F[CustomizeGlossaryTermBaseClass] -->|direct import| C G[GlossaryDetails.component\nlazy: GlossaryHeader\nlazy: ActivityFeedTab\nlazy: TabsLabel\nlazy: GenericTab\nlazy: OntologyExplorer\nlazy: AlignRightIconButton] H[GlossaryTermsV1.component\nlazy: GlossaryHeader] I[GlossaryTermUtils.tsx\nlazy: TabsLabel\nlazy: ActivityFeedTab\nlazy: GenericTab\nlazy: AssetsTabs\nlazy: GlossaryTermTab\nlazy: OntologyExplorer\nlazy: ResizablePanels]Reviews (1): Last reviewed commit: "perf(ui): lazy load glossary customizati..." | Re-trigger Greptile