From ac6c2fbb80ecaeac1d44698a15fc7b4de458f3a6 Mon Sep 17 00:00:00 2001 From: Patrick Balsiger Date: Sun, 31 Aug 2025 14:27:33 +0200 Subject: [PATCH] perf(startup): remove blocking components loader wait; defer component instantiation until navigation; trigger initial cluster load immediately --- public/scripts/app.js | 9 +-------- public/scripts/components/ClusterViewComponent.js | 15 +++++++-------- public/scripts/framework.js | 14 +++++++++++--- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/public/scripts/app.js b/public/scripts/app.js index 1ee982a..ed17044 100644 --- a/public/scripts/app.js +++ b/public/scripts/app.js @@ -8,14 +8,7 @@ document.addEventListener('DOMContentLoaded', async function() { logger.debug('App: Creating framework instance...'); const app = window.app; - // Wait for components to be ready (loader ensures constructors exist) - try { - if (typeof window.waitForComponentsReady === 'function') { - await window.waitForComponentsReady(); - } - } catch (e) { - logger.warn('App: Components loader timeout; proceeding anyway'); - } + // Components are loaded via script tags in order; no blocking wait required // Create view models logger.debug('App: Creating view models...'); diff --git a/public/scripts/components/ClusterViewComponent.js b/public/scripts/components/ClusterViewComponent.js index 1164b02..f341e2e 100644 --- a/public/scripts/components/ClusterViewComponent.js +++ b/public/scripts/components/ClusterViewComponent.js @@ -49,18 +49,17 @@ class ClusterViewComponent extends Component { // Only load data if we haven't already or if the view model is empty const members = this.viewModel.get('members'); - const shouldLoadData = !this.dataLoaded || !members || members.length === 0; + const shouldLoadData = true; // always perform initial refresh quickly if (shouldLoadData) { logger.debug('ClusterViewComponent: Starting initial data load...'); // Initial data load - ensure it happens after mounting - setTimeout(() => { - this.viewModel.updateClusterMembers().then(() => { - this.dataLoaded = true; - }).catch(error => { - logger.error('ClusterViewComponent: Failed to load initial data:', error); - }); - }, 100); + // Trigger immediately to reduce perceived startup latency + this.viewModel.updateClusterMembers().then(() => { + this.dataLoaded = true; + }).catch(error => { + logger.error('ClusterViewComponent: Failed to load initial data:', error); + }); } else { logger.debug('ClusterViewComponent: Data already loaded, skipping initial load'); } diff --git a/public/scripts/framework.js b/public/scripts/framework.js index d1d32bd..c33d474 100644 --- a/public/scripts/framework.js +++ b/public/scripts/framework.js @@ -635,8 +635,8 @@ class App { registerRoute(name, componentClass, containerId, viewModel = null) { this.routes.set(name, { componentClass, containerId, viewModel }); - // Pre-initialize component in cache for better performance - this.preInitializeComponent(name, componentClass, containerId, viewModel); + // Defer instantiation until navigation to reduce startup work + // this.preInitializeComponent(name, componentClass, containerId, viewModel); } // Pre-initialize component in cache @@ -771,7 +771,15 @@ class App { async showView(routeName, component) { const container = component.container; - // Ensure component is mounted (but not necessarily active) + // Ensure component is mounted (but not necessarily active); lazy-create now if needed + if (!component) { + const route = this.routes.get(routeName); + const container = document.getElementById(route.containerId); + component = new route.componentClass(container, route.viewModel, this.eventBus); + component.routeName = routeName; + component.isCached = true; + this.componentCache.set(routeName, component); + } if (!component.isMounted) { logger.debug(`App: Mounting component for '${routeName}'`); component.mount();