Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions apps/desktop/scripts/dev-renderer-warmup.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
* Resolve the renderer entry before Electron starts. This lets Vite finish
* dependency optimization and prevents a first navigation from combining
* modules from two optimizer generations.
*/
export async function warmupDevRenderer(server, entry = '/main.tsx') {
const environment = server.environments?.client;
if (environment?.warmupRequest && environment?.waitForRequestsIdle) {
await environment.warmupRequest(entry);
await environment.waitForRequestsIdle();
return;
}

// Vite 7 and earlier expose the same operation on the server. Keep this
// fallback for local installs that have not moved to per-environment APIs.
await server.warmupRequest(entry);
}
50 changes: 50 additions & 0 deletions apps/desktop/scripts/dev-renderer-warmup.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import assert from 'node:assert/strict';
import test from 'node:test';
import { warmupDevRenderer } from './dev-renderer-warmup.mjs';

test('warms the client environment and waits for its imports to settle', async () => {
const calls = [];
const server = {
environments: {
client: {
async warmupRequest(url) { calls.push(`warmup:${url}`); },
async waitForRequestsIdle() { calls.push('idle'); },
},
},
async warmupRequest() { throw new Error('legacy server API should not be used'); },
};

await warmupDevRenderer(server);

assert.deepEqual(calls, ['warmup:/main.tsx', 'idle']);
});

test('falls back to the server warmup API for older Vite versions', async () => {
const calls = [];
const server = {
async warmupRequest(url) { calls.push(url); },
};

await warmupDevRenderer(server, '/legacy.tsx');

assert.deepEqual(calls, ['/legacy.tsx']);
});
2 changes: 2 additions & 0 deletions apps/desktop/scripts/dev.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
handleDevelopmentLaunchOutcome,
waitForDevelopmentLaunchVerdict,
} from './dev-app-runtime.mjs';
import { warmupDevRenderer } from './dev-renderer-warmup.mjs';

const DESKTOP_DIR = resolve(fileURLToPath(new URL('..', import.meta.url)));
const REPO_ROOT = resolve(DESKTOP_DIR, '..', '..');
Expand Down Expand Up @@ -151,6 +152,7 @@ process.chdir(DESKTOP_DIR);
log('vite', 'starting dev server...');
const server = await createServer();
await server.listen();
await warmupDevRenderer(server);
server.printUrls();

const devUrl = server.resolvedUrls?.local?.[0]?.replace(/\/$/, '');
Expand Down
46 changes: 46 additions & 0 deletions apps/desktop/src/main/__tests__/main-renderer-loader.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import assert from 'node:assert/strict';
import test from 'node:test';
import { clearDevRendererCache, type MainRendererCacheOwner } from '../main-renderer-loader.js';

test('clears the renderer session cache only for a Vite development entry', async () => {
let clearCount = 0;
const owner: MainRendererCacheOwner = {
webContents: {
session: {
async clearCache() { clearCount += 1; },
},
},
};

await clearDevRendererCache(owner, {
filePath: '/app/dist-renderer/index.html',
url: 'http://127.0.0.1:5173',
useDevServer: true,
});
await clearDevRendererCache(owner, {
filePath: '/app/dist-renderer/index.html',
url: 'file:///app/dist-renderer/index.html',
useDevServer: false,
});

assert.equal(clearCount, 1);
});
15 changes: 15 additions & 0 deletions apps/desktop/src/main/main-renderer-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ export interface MainRendererEntry {
readonly useDevServer: boolean;
}

export interface MainRendererCacheOwner {
webContents: {
session: {
clearCache(): Promise<void>;
};
};
}

export async function clearDevRendererCache(
mainWindow: MainRendererCacheOwner,
rendererEntry: MainRendererEntry,
): Promise<void> {
if (rendererEntry.useDevServer) await mainWindow.webContents.session.clearCache();
}

export function resolveMainRendererEntry(
mainModuleDirectory: string,
viteDevServerUrl: string | undefined,
Expand Down
7 changes: 6 additions & 1 deletion apps/desktop/src/main/main-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ import { BrowserViewController } from './browser/controller.js';
import { BrowserViewManager } from './browser/view-manager.js';
import type { E2eFixture } from './e2e-fixture.js';
import { installMainWindowPermissionPolicy } from './main-window-permission-policy.js';
import { loadMainRenderer, resolveMainRendererEntry } from './main-renderer-loader.js';
import {
clearDevRendererCache,
loadMainRenderer,
resolveMainRendererEntry,
} from './main-renderer-loader.js';
import {
type MainRendererFrameIdentity,
observeMainRendererProcessGone,
Expand Down Expand Up @@ -522,6 +526,7 @@ export function createMainWindowController(deps: MainWindowControllerDeps): Main
void writeSavedBounds(workspaceRoot, final);
});

await clearDevRendererCache(mainWindow, rendererEntry);
await loadMainRenderer(mainWindow, rendererEntry);

// PR-SHOW-AFTER-FIRST-COMMIT: reveal fallback. Start this budget only once
Expand Down