mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-06 11:48:46 +02:00
perf: improve application startup performance
Renderer code splitting: - Lazy-load 15 components with React.lazy() and Suspense (ChatPane, ActivityPanel, SettingsPanel, TerminalPanel, WelcomePane, BottomPanel, GitPanel, CommandPalette, CommitComposer, WorkflowPicker, BookmarksPanel, SessionSearchPanel, KeyboardShortcutsPanel, DiscoveredToolingModal, ProjectSettingsPanel) - This moves ~1.2 MB of optional dependencies (Lexical, @xyflow/react, @xterm/xterm, highlight.js, motion) out of the critical bundle - Critical bundle reduced from ~1.5 MB to ~759 KB - Defer JetBrains Mono font load to TerminalPanel (saves ~80 KB at startup) Main process optimizations: - Use show: false + ready-to-show on BrowserWindow to eliminate blank flash - Decouple workspace loading from bootstrap — no longer blocks window, tray, and auto-update setup - Defer sidecar-dependent approval tool pruning to run in background after workspace is returned to renderer (removes sidecar spawn from critical path) - Parallelize independent workspace sync operations (user tooling, project tooling, project customization) with Promise.all() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -473,27 +473,43 @@ export class AryxAppService extends EventEmitter<AppServiceEvents> {
|
||||
const selectedProject = selectedProjectId
|
||||
? this.workspace.projects.find((project) => project.id === selectedProjectId)
|
||||
: undefined;
|
||||
const didSyncUserTooling = await this.syncUserDiscoveredTooling(this.workspace);
|
||||
const didSyncProjectTooling = selectedProject
|
||||
? await this.syncProjectDiscoveredTooling(this.workspace, selectedProject)
|
||||
: false;
|
||||
const didSyncProjectCustomization = selectedProject
|
||||
? await this.syncProjectCustomization(selectedProject)
|
||||
: false;
|
||||
|
||||
// Run independent sync operations in parallel
|
||||
const [didSyncUserTooling, didSyncProjectTooling, didSyncProjectCustomization] = await Promise.all([
|
||||
this.syncUserDiscoveredTooling(this.workspace),
|
||||
selectedProject
|
||||
? this.syncProjectDiscoveredTooling(this.workspace, selectedProject)
|
||||
: false,
|
||||
selectedProject
|
||||
? this.syncProjectCustomization(selectedProject)
|
||||
: false,
|
||||
]);
|
||||
|
||||
const didPruneSelections = this.pruneUnavailableSessionToolingSelections(this.workspace);
|
||||
const didPruneApprovalTools = await this.pruneUnavailableApprovalTools(this.workspace);
|
||||
if (
|
||||
didSyncUserTooling
|
||||
|| didSyncProjectTooling
|
||||
|| didSyncProjectCustomization
|
||||
|| didPruneSelections
|
||||
|| didPruneApprovalTools
|
||||
|| this.cleanupInterruptedSessions(this.workspace)
|
||||
) {
|
||||
await this.workspaceRepository.save(this.workspace);
|
||||
}
|
||||
|
||||
await this.syncProjectCustomizationWatchers(this.workspace);
|
||||
|
||||
// Defer sidecar-dependent approval pruning so it doesn't block startup.
|
||||
// This runs in the background and emits workspace-updated when done.
|
||||
void this.pruneUnavailableApprovalTools(this.workspace)
|
||||
.then(async (didPrune) => {
|
||||
if (didPrune && this.workspace) {
|
||||
await this.workspaceRepository.save(this.workspace);
|
||||
this.emit('workspace-updated', this.workspace);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('[aryx startup] deferred approval tool pruning failed', error);
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.didScheduleInitialProjectGitRefresh) {
|
||||
|
||||
+27
-19
@@ -23,21 +23,34 @@ async function bootstrap(): Promise<void> {
|
||||
mainWindow = createMainWindow();
|
||||
registerIpcHandlers(mainWindow, appService, autoUpdateService);
|
||||
|
||||
// Apply persisted theme to the title bar overlay
|
||||
const workspace = await appService.loadWorkspace();
|
||||
applyTitleBarTheme(mainWindow, workspace.settings.theme);
|
||||
// Start workspace loading in parallel — don't block window from showing.
|
||||
// The renderer fetches the workspace via its own IPC call after mount.
|
||||
const workspaceReady = appService.loadWorkspace();
|
||||
|
||||
// Set up system tray
|
||||
systemTray = new SystemTray({
|
||||
onShowWindow: showAndFocusWindow,
|
||||
onCreateScratchpad: () => {
|
||||
showAndFocusWindow();
|
||||
mainWindow?.webContents.send('tray:create-scratchpad');
|
||||
},
|
||||
onQuit: () => app.quit(),
|
||||
});
|
||||
systemTray.create();
|
||||
systemTray.updateRunningCount(workspace);
|
||||
// Apply theme and set up tray once workspace is available
|
||||
workspaceReady
|
||||
.then((workspace) => {
|
||||
if (!mainWindow) return;
|
||||
applyTitleBarTheme(mainWindow, workspace.settings.theme);
|
||||
|
||||
systemTray = new SystemTray({
|
||||
onShowWindow: showAndFocusWindow,
|
||||
onCreateScratchpad: () => {
|
||||
showAndFocusWindow();
|
||||
mainWindow?.webContents.send('tray:create-scratchpad');
|
||||
},
|
||||
onQuit: () => app.quit(),
|
||||
});
|
||||
systemTray.create();
|
||||
systemTray.updateRunningCount(workspace);
|
||||
|
||||
appService!.on('workspace-updated', (updatedWorkspace) => {
|
||||
systemTray?.updateRunningCount(updatedWorkspace);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('[aryx bootstrap] workspace load failed', error);
|
||||
});
|
||||
|
||||
// Intercept close to hide to tray when the setting is enabled
|
||||
setupCloseToTray(mainWindow, () => {
|
||||
@@ -45,11 +58,6 @@ async function bootstrap(): Promise<void> {
|
||||
return currentWorkspace?.settings.minimizeToTray === true;
|
||||
});
|
||||
|
||||
// Keep tray status in sync when workspace changes
|
||||
appService.on('workspace-updated', (updatedWorkspace) => {
|
||||
systemTray?.updateRunningCount(updatedWorkspace);
|
||||
});
|
||||
|
||||
if (!app.isPackaged) {
|
||||
mainWindow.webContents.openDevTools({ mode: 'detach' });
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ export function createMainWindow(): BrowserWindowType {
|
||||
height: 960,
|
||||
minWidth: 1120,
|
||||
minHeight: 720,
|
||||
show: false,
|
||||
title: 'aryx',
|
||||
icon: resolveWindowIconPath({
|
||||
appPath: app.getAppPath(),
|
||||
@@ -36,6 +37,10 @@ export function createMainWindow(): BrowserWindowType {
|
||||
},
|
||||
});
|
||||
|
||||
window.once('ready-to-show', () => {
|
||||
window.show();
|
||||
});
|
||||
|
||||
const rendererUrl = process.env.ELECTRON_RENDERER_URL;
|
||||
|
||||
if (rendererUrl) {
|
||||
|
||||
Reference in New Issue
Block a user