Skip to content

refactor: lazy-load webview panel modules via shared cache#66

Open
CompN3rd wants to merge 2 commits into
mainfrom
perf/dynamic-imports
Open

refactor: lazy-load webview panel modules via shared cache#66
CompN3rd wants to merge 2 commits into
mainfrom
perf/dynamic-imports

Conversation

@CompN3rd
Copy link
Copy Markdown
Owner

Decouples PlanningPanel, PrDetailsPanel, PipelineRunDetailsPanel from the activation import graph. Each is now reached via a shared src/views/lazyPanels.ts loader that caches the dynamic import promise so all callers observe the same loaded-or-not state.

Why shared cache

Static refresh methods (PrDetailsPanel.refreshAllOpenPanels, PlanningPanel.refreshOpenPanels) are invoked from config-change handlers and toggle commands that must no-op when the module was never opened. The cache lets these paths check *PanelLoaded() and skip the refresh entirely, instead of forcing a load just to discover there are no open panels.

Inlining await import('../views/prDetailsPanel') per call site would create one cache per importer, and the shared-state check in extension.ts would observe stale undefined even after the command path had already loaded and opened a panel — silent missed refresh.

Honest scoping note

The extension host bundle is currently CJS without splitting, so esbuild inlines dynamic imports as wrapped require() calls. The lazy modules are still parsed at activation today, so this PR does not improve activation time on its own.

This change is purely structural and unblocks a future move to ESM + splitting (or manual external chunks via separate esbuild entries) where the deferred parse would actually take effect.

Verification

  • npm run compile clean
  • npm run lint clean
  • Bundle size unchanged (1.3mb — expected, see above)

Files

  • new src/views/lazyPanels.ts
  • src/extension.ts — uses loadPlanningPanel, loadPipelineRunDetailsPanel, planningPanelLoaded, prDetailsPanelLoaded
  • src/commands/pullRequestCommands.ts — uses loadPrDetailsPanel
  • src/commands/pipelineCommands.ts — uses loadPipelineRunDetailsPanel

Decouple PlanningPanel, PrDetailsPanel, PipelineRunDetailsPanel from the
activation import graph. Each is now reached via a shared lazyPanels.ts
loader that caches the dynamic import promise so all callers observe the
same loaded-or-not state. This matters for static refresh methods
(refreshAllOpenPanels, refreshOpenPanels) which must no-op when the
module was never opened; they consult *PanelLoaded() instead of forcing
a load.

Honest scoping note: the extension host bundle is currently CJS without
splitting, so esbuild inlines dynamic imports as wrapped require() calls
and the modules are still parsed at activation. This change is purely
structural and unblocks a future move to ESM + splitting (or manual
external chunks) where the deferred parse would actually take effect.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors webview panel entrypoints to be reached through a shared lazy-loader so extension.ts and command modules can coordinate “module has ever been requested” state and avoid loading panels solely to run no-op static refresh methods.

Changes:

  • Added src/views/lazyPanels.ts with cached dynamic-import loaders for Planning, PR Details, and Pipeline Run Details panels.
  • Updated src/extension.ts to remove direct panel imports and to guard refresh calls behind *PanelLoaded() checks.
  • Updated PR/pipeline command handlers to load panel modules via the shared loader before calling *.show().

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/views/lazyPanels.ts Introduces shared cached dynamic-import loaders and “loaded” helpers for panel modules.
src/extension.ts Replaces static panel imports with shared lazy loading and conditional refresh behavior.
src/commands/pullRequestCommands.ts Loads PrDetailsPanel via shared loader before showing details panel.
src/commands/pipelineCommands.ts Loads PipelineRunDetailsPanel via shared loader before showing run details panel.

Comment thread src/views/lazyPanels.ts Outdated
Comment on lines +8 to +17
export const planningPanelLoaded = () => _planning;

let _prDetails: Promise<typeof import('./prDetailsPanel')> | undefined;
export const loadPrDetailsPanel = () => (_prDetails ??= import('./prDetailsPanel'));
export const prDetailsPanelLoaded = () => _prDetails;

let _pipelineRun: Promise<typeof import('./pipelineRunDetailsPanel')> | undefined;
export const loadPipelineRunDetailsPanel = () =>
(_pipelineRun ??= import('./pipelineRunDetailsPanel'));
export const pipelineRunDetailsPanelLoaded = () => _pipelineRun;
The reviewer flagged the old name as misleading: it returns the cached
import promise iff loadXPanel() was previously called, not a boolean
'is loaded' state. New names follow the loadX / loadedX convention used
elsewhere for lazy module accessors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants