Skip to content

perf(ui): lazy load glossary customization views#29180

Open
shah-harshit wants to merge 1 commit into
feat/dashboard-lcp-parentfrom
feat/dashboard-lcp-04-glossary
Open

perf(ui): lazy load glossary customization views#29180
shah-harshit wants to merge 1 commit into
feat/dashboard-lcp-parentfrom
feat/dashboard-lcp-04-glossary

Conversation

@shah-harshit

@shah-harshit shah-harshit commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Extracts glossary/glossary-term widget utilities and lazy-loads glossary customization/detail surfaces.
  • Split from the dashboard LCP optimization work so it can be reviewed independently.

Testing

  • Not run; tests will be fixed separately for this PR.

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 lazy withSuspenseFallback wrappers, reducing initial bundle size and deferring LCP-blocking modules.

  • New utility split: GlossaryTermUtil.tsx is now a thin barrel; GlossaryTermReferenceUtils holds pure reference helpers, and GlossaryTermWidgetUtils holds the widget factory with all component imports deferred via lazy(). Key consumers are updated to direct import paths.
  • Lazy-loading sweep: GlossaryHeader, ActivityFeedTab, GenericTab, OntologyExplorer, ResizablePanels, AssetsTabs, GlossaryTermTab, and several smaller components in GlossaryDetails, GlossaryTermsV1, and GlossaryTermUtils are all converted to dynamic imports wrapped with withSuspenseFallback.
  • Import path corrections: getEntityDeleteMessage / getEntityMissingError updated to EntityDisplayPureUtils, isTaskPendingFurtherApproval moved to TaskNavigationUtils, and createGlossaryTermEntityLink to GlossaryTermReferenceUtils — 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

Filename Overview
openmetadata-ui/src/main/resources/ui/src/utils/GlossaryTerm/GlossaryTermWidgetUtils.tsx New file extracted from GlossaryTermUtil; contains widget-factory logic with all heavy components lazy-loaded. GlossaryTermDomainWidget is declared after getGlossaryTermWidgetFromKey that references it (inherited ordering from original file, safe at runtime).
openmetadata-ui/src/main/resources/ui/src/utils/GlossaryTerm/GlossaryTermReferenceUtils.tsx New pure-utility file extracted from GlossaryTermUtil; no React hooks or lazy imports, suitable for reference-only consumers wanting a lightweight import path.
openmetadata-ui/src/main/resources/ui/src/utils/GlossaryTerm/GlossaryTermUtil.tsx Now a thin barrel re-exporting both new files for backward compatibility; the widget utils re-export still bundles React context and lazy-wrapper code for all barrel consumers.
openmetadata-ui/src/main/resources/ui/src/utils/CustomizeGlossaryTerm/CustomizeGlossaryTermBaseClass.ts Direct imports removed and replaced with lazy withSuspenseFallback wrappers; ComponentMap types broadened to ComponentType; now imports getGlossaryTermWidgetFromKey directly from GlossaryTermWidgetUtils.
openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryDetails/GlossaryDetails.component.tsx GlossaryHeader, ActivityFeedTab, TabsLabel, GenericTab, OntologyExplorer, and AlignRightIconButton all converted to lazy withSuspenseFallback; the full-screen Loader fallback on small inline components (TabsLabel, AlignRightIconButton) may cause layout shift on first load.
openmetadata-ui/src/main/resources/ui/src/utils/Glossary/GlossaryTermUtils.tsx TabsLabel, ActivityFeedTab, GenericTab, AssetsTabs, GlossaryTermTab, OntologyExplorer, and ResizablePanels all converted to lazy withSuspenseFallback; logic is otherwise unchanged.

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]
Loading
%%{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]
Loading

Reviews (1): Last reviewed commit: "perf(ui): lazy load glossary customizati..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

@shah-harshit shah-harshit requested a review from a team as a code owner June 18, 2026 10:32
@shah-harshit shah-harshit added UI UI specific issues safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check labels Jun 18, 2026
@shah-harshit shah-harshit self-assigned this Jun 18, 2026
patchGlossaryTerm,
} from '../../rest/glossaryAPI';
import { getEntityDeleteMessage } from '../../utils/EntityDisplayUtils';
import { getEntityDeleteMessage } from '../../utils/EntityDisplayPureUtils';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 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:

  1. EntityDisplayPureUtils — does not exist. Only src/utils/EntityDisplayUtils.tsx exists, which is where getCountBadge, getEntityDeleteMessage, and getEntityMissingError are 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'
  2. TaskNavigationUtils — does not exist. isTaskPendingFurtherApproval is exported from src/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 👍 / 👎

@gitar-bot

gitar-bot Bot commented Jun 18, 2026

Copy link
Copy Markdown
Code Review 🚫 Blocked 0 resolved / 1 findings

Lazy 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:

  1. EntityDisplayPureUtils — does not exist. Only src/utils/EntityDisplayUtils.tsx exists, which is where getCountBadge, getEntityDeleteMessage, and getEntityMissingError are 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'
  2. TaskNavigationUtils — does not exist. isTaskPendingFurtherApproval is exported from src/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';
🤖 Prompt for agents
Code Review: Lazy loads glossary customization views to improve dashboard performance, but the changes are blocked because they reference non-existent utility modules, causing build failures.

1. 🚨 Bug: Imports reference non-existent util modules (build break)
   Files: 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:
   
   1. `EntityDisplayPureUtils` — does not exist. Only `src/utils/EntityDisplayUtils.tsx` exists, which is where `getCountBadge`, `getEntityDeleteMessage`, and `getEntityMissingError` are 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'`
   
   2. `TaskNavigationUtils` — does not exist. `isTaskPendingFurtherApproval` is exported from `src/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 d86fd803 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`).

   Fix (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';

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Comment on lines +14 to +15
export * from './GlossaryTermReferenceUtils';
export * from './GlossaryTermWidgetUtils';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 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!

Comment on lines +54 to +70
)
);

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'))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 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!

@shah-harshit shah-harshit changed the base branch from main to feat/dashboard-lcp-parent June 18, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant