From 8d068549cb36da8465e22465e09401366987e0e2 Mon Sep 17 00:00:00 2001 From: Lum1104 Date: Sun, 3 May 2026 17:14:04 +0800 Subject: [PATCH] fix(dashboard): address final review C1 + C2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C1 (cache leak across topology changes): Container ids derive from folder names (`container:auth`, etc.) and collide across layers, personas, and node-type filters. Without a reset, navigating from Layer A to Layer B left Stage 2's cache and size memory keyed by Layer A children, so Stage 2 short-circuited and Layer B's children silently disappeared. Reset containerLayoutCache, containerSizeMemory, and expandedContainers in: - drillIntoLayer (most visible — layer drill) - navigateToOverview (drilling out) - toggleNodeTypeFilter (filter change shifts container.nodeIds) - setPersona (persona filters node types) setGraph already resets all three on full graph reload — unchanged. C2 (bundle regression): Add elkjs and graphology rules to vite manualChunks. The main index chunk drops from 525KB gzipped back to 62KB, with ELK split into a parallel-loadable 439KB chunk. Restores baseline first-paint cost. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../packages/dashboard/src/store.ts | 24 ++++++++++++++++++- .../packages/dashboard/vite.config.ts | 4 ++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/understand-anything-plugin/packages/dashboard/src/store.ts b/understand-anything-plugin/packages/dashboard/src/store.ts index d1bef11..a8cfdf1 100644 --- a/understand-anything-plugin/packages/dashboard/src/store.ts +++ b/understand-anything-plugin/packages/dashboard/src/store.ts @@ -244,6 +244,12 @@ export const useDashboardStore = create()((set, get) => ({ ...state.nodeTypeFilters, [category]: !state.nodeTypeFilters[category], }, + // Filter changes shift container.nodeIds; cached child positions + // may reference filtered-out children. Drop the cache so Stage 2 + // recomputes against the current set. + containerLayoutCache: new Map(), + containerSizeMemory: new Map(), + expandedContainers: new Set(), })), setGraph: (graph) => { @@ -359,6 +365,12 @@ export const useDashboardStore = create()((set, get) => ({ codeViewerOpen: false, codeViewerNodeId: null, codeViewerExpanded: false, + // Container ids derive from folder names and collide across layers + // (e.g. `container:auth` exists in many layers). Drop the cache so + // we don't render stale positions for the new layer's children. + containerLayoutCache: new Map(), + containerSizeMemory: new Map(), + expandedContainers: new Set(), }), navigateToOverview: () => @@ -370,6 +382,9 @@ export const useDashboardStore = create()((set, get) => ({ codeViewerOpen: false, codeViewerNodeId: null, codeViewerExpanded: false, + containerLayoutCache: new Map(), + containerSizeMemory: new Map(), + expandedContainers: new Set(), }), setFocusNode: (nodeId) => set({ focusNodeId: nodeId, selectedNodeId: nodeId }), @@ -388,7 +403,14 @@ export const useDashboardStore = create()((set, get) => ({ set({ searchQuery: query, searchResults }); }, - setPersona: (persona) => set({ persona }), + setPersona: (persona) => + set({ + persona, + // Persona changes filter node types, which shifts container.nodeIds. + containerLayoutCache: new Map(), + containerSizeMemory: new Map(), + expandedContainers: new Set(), + }), openCodeViewer: (nodeId) => set({ codeViewerOpen: true, codeViewerNodeId: nodeId, codeViewerExpanded: false }), diff --git a/understand-anything-plugin/packages/dashboard/vite.config.ts b/understand-anything-plugin/packages/dashboard/vite.config.ts index 3507902..34718f4 100644 --- a/understand-anything-plugin/packages/dashboard/vite.config.ts +++ b/understand-anything-plugin/packages/dashboard/vite.config.ts @@ -207,6 +207,10 @@ export default defineConfig({ return "react-vendor"; } if (id.includes("node_modules/@xyflow/")) return "xyflow"; + // ELK is ~1.6MB raw — split into its own chunk so it doesn't + // bloat the main bundle. graphology is similarly large. + if (id.includes("node_modules/elkjs/")) return "elk"; + if (id.includes("node_modules/graphology")) return "graphology"; if ( id.includes("node_modules/@dagrejs/") || id.includes("node_modules/d3-force/")