Skip to content

Commit 3feefd9

Browse files
authored
perf(browser): cut per-file round trips (#10730)
1 parent b60605c commit 3feefd9

4 files changed

Lines changed: 47 additions & 7 deletions

File tree

packages/browser/src/client/orchestrator.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,8 @@ function generateFileId(file: string) {
576576
)
577577
}
578578

579+
let currentViewport: { width: number; height: number } | undefined
580+
579581
async function setIframeViewport(
580582
width: number,
581583
height: number,
@@ -589,12 +591,26 @@ async function setIframeViewport(
589591
document.body.style.setProperty('--viewport-width', `${width}px`)
590592
document.body.style.setProperty('--viewport-height', `${height}px`)
591593

594+
// playwright emulates the viewport per page, so it keeps its size
595+
// between test files and the command round trip is only needed when
596+
// the size actually changes; other providers resize the window, which
597+
// outside code can move under us, so they always re-pin
598+
const cacheable = getBrowserState().provider === 'playwright'
599+
if (
600+
cacheable
601+
&& currentViewport?.width === width
602+
&& currentViewport?.height === height
603+
) {
604+
return
605+
}
606+
592607
await client.rpc.triggerCommand(
593608
getBrowserState().sessionId,
594609
'__vitest_viewport',
595610
undefined,
596611
[{ width, height }],
597612
)
613+
currentViewport = cacheable ? { width, height } : undefined
598614
}
599615
}
600616

packages/browser/src/client/tester/runner.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export function createBrowserRunner(
5858
public config: SerializedConfig
5959
public hashMap = browserHashMap
6060
public sourceMapCache = new Map<string, any>()
61+
private sourceMapPrefetches = new Map<string, Promise<any>>()
6162
public method = 'run' as TestExecutionMethod
6263
private commands: CommandsManager
6364

@@ -218,7 +219,13 @@ export function createBrowserRunner(
218219
if (!('filepath' in suite)) {
219220
return
220221
}
221-
const map = await rpc().getBrowserFileSourceMap(suite.filepath)
222+
// usually resolved already: the request is fired as soon as the
223+
// file finishes importing, while collection is still running
224+
const map = await (
225+
this.sourceMapPrefetches.get(suite.filepath)
226+
?? rpc().getBrowserFileSourceMap(suite.filepath)
227+
)
228+
this.sourceMapPrefetches.delete(suite.filepath)
222229
this.sourceMapCache.set(suite.filepath, map)
223230
const snapshotEnvironment = this.config.snapshotOptions.snapshotEnvironment
224231
if (snapshotEnvironment instanceof VitestBrowserSnapshotEnvironment) {
@@ -334,6 +341,15 @@ export function createBrowserRunner(
334341
catch (err) {
335342
throw new Error(`Failed to import test file ${filepath}`, { cause: err })
336343
}
344+
345+
if (mode === 'collect' && !this.sourceMapPrefetches.has(filepath)) {
346+
// the file is transformed now, so the server can hand out its map;
347+
// request it early so onBeforeRunSuite doesn't have to wait
348+
this.sourceMapPrefetches.set(
349+
filepath,
350+
rpc().getBrowserFileSourceMap(filepath).catch(() => undefined),
351+
)
352+
}
337353
}
338354

339355
trace = <T>(name: string, attributes: Record<string, any> | (() => T), cb?: () => T): T => {

packages/browser/src/node/project.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ import { getBrowserProvider } from './utils'
2222
export class ProjectBrowser implements IProjectBrowser {
2323
public testerHtml: Promise<string> | string
2424
public testerFilepath: string
25+
// the tester template is read once per server, so the transformed HTML
26+
// is stable too — computing it for every iframe request pays the whole
27+
// transformIndexHtml plugin pipeline each time
28+
public testerHtmlTransformed: Promise<string> | undefined
2529

2630
public provider!: BrowserProvider
2731
public vitest: Vitest

packages/browser/src/node/serverTester.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,24 @@ export async function resolveTester(
5959
__VITEST_API_TOKEN__: JSON.stringify(globalServer.vitest.config.api.token),
6060
})
6161

62-
const testerHtml = typeof browserProject.testerHtml === 'string'
63-
? browserProject.testerHtml
64-
: await browserProject.testerHtml
65-
6662
try {
67-
const url = join('/@fs/', browserProject.testerFilepath)
68-
const indexhtml = await browserProject.vite.transformIndexHtml(url, testerHtml)
63+
browserProject.testerHtmlTransformed ??= (async () => {
64+
const testerHtml = typeof browserProject.testerHtml === 'string'
65+
? browserProject.testerHtml
66+
: await browserProject.testerHtml
67+
const url = join('/@fs/', browserProject.testerFilepath)
68+
return await browserProject.vite.transformIndexHtml(url, testerHtml)
69+
})()
70+
const indexhtml = await browserProject.testerHtmlTransformed
6971
const html = replacer(indexhtml, {
7072
__VITEST_FAVICON__: globalServer.faviconUrl,
7173
__VITEST_INJECTOR__: injector,
7274
})
7375
return html
7476
}
7577
catch (err: any) {
78+
// don't cache a rejection — the next request should retry the transform
79+
browserProject.testerHtmlTransformed = undefined
7680
session.fail(err)
7781
next(err)
7882
}

0 commit comments

Comments
 (0)
Sponsor
SponsoredKunjungi sekarang
Promo