From aa52792aebcfde48ad7e72edc79d5d8ef10135aa Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 10 Jul 2024 08:44:31 +0200 Subject: [PATCH] perf(browser): don't import msw if no modules are mocked (#6073) --- packages/browser/src/client/tester/msw.ts | 83 +++++++++++----------- packages/browser/src/client/vite.config.ts | 11 +-- packages/browser/src/node/plugin.ts | 14 ---- packages/browser/src/node/server.ts | 8 +-- 4 files changed, 47 insertions(+), 69 deletions(-) diff --git a/packages/browser/src/client/tester/msw.ts b/packages/browser/src/client/tester/msw.ts index f66738b96c8e..da7a244ec0aa 100644 --- a/packages/browser/src/client/tester/msw.ts +++ b/packages/browser/src/client/tester/msw.ts @@ -1,5 +1,3 @@ -import { http } from 'msw/core/http' -import { setupWorker } from 'msw/browser' import type { IframeChannelEvent, IframeMockEvent, @@ -11,43 +9,6 @@ import { channel } from '../channel' export function createModuleMocker() { const mocks: Map = new Map() - const worker = setupWorker( - http.get(/.+/, async ({ request }) => { - const path = cleanQuery(request.url.slice(location.origin.length)) - if (!mocks.has(path)) { - return passthrough() - } - - const mock = mocks.get(path) - - // using a factory - if (mock === undefined) { - const exports = await getFactoryExports(path) - const module = `const module = __vitest_mocker__.get('${path}');` - const keys = exports - .map((name) => { - if (name === 'default') { - return `export default module['default'];` - } - return `export const ${name} = module['${name}'];` - }) - .join('\n') - const text = `${module}\n${keys}` - return new Response(text, { - headers: { - 'Content-Type': 'application/javascript', - }, - }) - } - - if (typeof mock === 'string') { - return Response.redirect(mock) - } - - return Response.redirect(injectQuery(path, 'mock=auto')) - }), - ) - let started = false let startPromise: undefined | Promise @@ -58,13 +19,53 @@ export function createModuleMocker() { if (startPromise) { return startPromise } - startPromise = worker - .start({ + startPromise = Promise.all([ + import('msw/browser'), + import('msw/core/http'), + ]).then(([{ setupWorker }, { http }]) => { + const worker = setupWorker( + http.get(/.+/, async ({ request }) => { + const path = cleanQuery(request.url.slice(location.origin.length)) + if (!mocks.has(path)) { + return passthrough() + } + + const mock = mocks.get(path) + + // using a factory + if (mock === undefined) { + const exports = await getFactoryExports(path) + const module = `const module = __vitest_mocker__.get('${path}');` + const keys = exports + .map((name) => { + if (name === 'default') { + return `export default module['default'];` + } + return `export const ${name} = module['${name}'];` + }) + .join('\n') + const text = `${module}\n${keys}` + return new Response(text, { + headers: { + 'Content-Type': 'application/javascript', + }, + }) + } + + if (typeof mock === 'string') { + return Response.redirect(mock) + } + + return Response.redirect(injectQuery(path, 'mock=auto')) + }), + ) + return worker.start({ serviceWorker: { url: '/__vitest_msw__', }, quiet: true, }) + }) .finally(() => { started = true startPromise = undefined diff --git a/packages/browser/src/client/vite.config.ts b/packages/browser/src/client/vite.config.ts index 818e47607821..59e3ab89cde3 100644 --- a/packages/browser/src/client/vite.config.ts +++ b/packages/browser/src/client/vite.config.ts @@ -22,19 +22,10 @@ export default defineConfig({ orchestrator: resolve(__dirname, './orchestrator.html'), tester: resolve(__dirname, './tester/tester.html'), }, - external: [/__virtual_vitest__/, '@vitest/browser/context'], + external: [/^vitest\//, 'vitest', /^msw/, '@vitest/browser/context'], }, }, plugins: [ - { - name: 'virtual:msw', - enforce: 'pre', - resolveId(id) { - if (id.startsWith('msw') || id.startsWith('vitest') || id.startsWith('@vitest/browser')) { - return `/__virtual_vitest__?id=${encodeURIComponent(id)}` - } - }, - }, { name: 'copy-ui-plugin', /* eslint-disable no-console */ diff --git a/packages/browser/src/node/plugin.ts b/packages/browser/src/node/plugin.ts index 69b72649597b..51ebab897ef7 100644 --- a/packages/browser/src/node/plugin.ts +++ b/packages/browser/src/node/plugin.ts @@ -220,20 +220,6 @@ export default (browserServer: BrowserServer, base = '/'): Plugin[] => { { name: 'vitest:browser:resolve-virtual', async resolveId(rawId) { - if (rawId.startsWith('/__virtual_vitest__')) { - const url = new URL(rawId, 'http://localhost') - if (!url.searchParams.has('id')) { - return - } - - const id = decodeURIComponent(url.searchParams.get('id')!) - - const resolved = await this.resolve(id, distRoot, { - skipSelf: true, - }) - return resolved - } - if (rawId === '/__vitest_msw__') { return this.resolve('msw/mockServiceWorker.js', distRoot, { skipSelf: true, diff --git a/packages/browser/src/node/server.ts b/packages/browser/src/node/server.ts index 4ecc68b78dae..b833418e8c43 100644 --- a/packages/browser/src/node/server.ts +++ b/packages/browser/src/node/server.ts @@ -182,7 +182,7 @@ export class BrowserServer implements IBrowserServer { }) } - private cdpSessions = new Map>() + private cdpSessionsPromises = new Map>() async ensureCDPHandler(contextId: string, sessionId: string) { const cachedHandler = this.state.cdps.get(sessionId) @@ -195,11 +195,11 @@ export class BrowserServer implements IBrowserServer { throw new Error(`CDP is not supported by the provider "${provider.name}".`) } - const promise = this.cdpSessions.get(sessionId) ?? await (async () => { + const promise = this.cdpSessionsPromises.get(sessionId) ?? await (async () => { const promise = provider.getCDPSession!(contextId).finally(() => { - this.cdpSessions.delete(sessionId) + this.cdpSessionsPromises.delete(sessionId) }) - this.cdpSessions.set(sessionId, promise) + this.cdpSessionsPromises.set(sessionId, promise) return promise })()