Skip to content

Commit

Permalink
perf(browser): don't import msw if no modules are mocked (#6073)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va authored Jul 10, 2024
1 parent af7fec5 commit aa52792
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 69 deletions.
83 changes: 42 additions & 41 deletions packages/browser/src/client/tester/msw.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { http } from 'msw/core/http'
import { setupWorker } from 'msw/browser'
import type {
IframeChannelEvent,
IframeMockEvent,
Expand All @@ -11,43 +9,6 @@ import { channel } from '../channel'
export function createModuleMocker() {
const mocks: Map<string, string | null | undefined> = 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<unknown>

Expand All @@ -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
Expand Down
11 changes: 1 addition & 10 deletions packages/browser/src/client/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
14 changes: 0 additions & 14 deletions packages/browser/src/node/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 4 additions & 4 deletions packages/browser/src/node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export class BrowserServer implements IBrowserServer {
})
}

private cdpSessions = new Map<string, Promise<CDPSession>>()
private cdpSessionsPromises = new Map<string, Promise<CDPSession>>()

async ensureCDPHandler(contextId: string, sessionId: string) {
const cachedHandler = this.state.cdps.get(sessionId)
Expand All @@ -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
})()

Expand Down

0 comments on commit aa52792

Please sign in to comment.