Skip to content

Commit aa52792

Browse files
authored
perf(browser): don't import msw if no modules are mocked (#6073)
1 parent af7fec5 commit aa52792

File tree

4 files changed

+47
-69
lines changed

4 files changed

+47
-69
lines changed

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

+42-41
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { http } from 'msw/core/http'
2-
import { setupWorker } from 'msw/browser'
31
import type {
42
IframeChannelEvent,
53
IframeMockEvent,
@@ -11,43 +9,6 @@ import { channel } from '../channel'
119
export function createModuleMocker() {
1210
const mocks: Map<string, string | null | undefined> = new Map()
1311

14-
const worker = setupWorker(
15-
http.get(/.+/, async ({ request }) => {
16-
const path = cleanQuery(request.url.slice(location.origin.length))
17-
if (!mocks.has(path)) {
18-
return passthrough()
19-
}
20-
21-
const mock = mocks.get(path)
22-
23-
// using a factory
24-
if (mock === undefined) {
25-
const exports = await getFactoryExports(path)
26-
const module = `const module = __vitest_mocker__.get('${path}');`
27-
const keys = exports
28-
.map((name) => {
29-
if (name === 'default') {
30-
return `export default module['default'];`
31-
}
32-
return `export const ${name} = module['${name}'];`
33-
})
34-
.join('\n')
35-
const text = `${module}\n${keys}`
36-
return new Response(text, {
37-
headers: {
38-
'Content-Type': 'application/javascript',
39-
},
40-
})
41-
}
42-
43-
if (typeof mock === 'string') {
44-
return Response.redirect(mock)
45-
}
46-
47-
return Response.redirect(injectQuery(path, 'mock=auto'))
48-
}),
49-
)
50-
5112
let started = false
5213
let startPromise: undefined | Promise<unknown>
5314

@@ -58,13 +19,53 @@ export function createModuleMocker() {
5819
if (startPromise) {
5920
return startPromise
6021
}
61-
startPromise = worker
62-
.start({
22+
startPromise = Promise.all([
23+
import('msw/browser'),
24+
import('msw/core/http'),
25+
]).then(([{ setupWorker }, { http }]) => {
26+
const worker = setupWorker(
27+
http.get(/.+/, async ({ request }) => {
28+
const path = cleanQuery(request.url.slice(location.origin.length))
29+
if (!mocks.has(path)) {
30+
return passthrough()
31+
}
32+
33+
const mock = mocks.get(path)
34+
35+
// using a factory
36+
if (mock === undefined) {
37+
const exports = await getFactoryExports(path)
38+
const module = `const module = __vitest_mocker__.get('${path}');`
39+
const keys = exports
40+
.map((name) => {
41+
if (name === 'default') {
42+
return `export default module['default'];`
43+
}
44+
return `export const ${name} = module['${name}'];`
45+
})
46+
.join('\n')
47+
const text = `${module}\n${keys}`
48+
return new Response(text, {
49+
headers: {
50+
'Content-Type': 'application/javascript',
51+
},
52+
})
53+
}
54+
55+
if (typeof mock === 'string') {
56+
return Response.redirect(mock)
57+
}
58+
59+
return Response.redirect(injectQuery(path, 'mock=auto'))
60+
}),
61+
)
62+
return worker.start({
6363
serviceWorker: {
6464
url: '/__vitest_msw__',
6565
},
6666
quiet: true,
6767
})
68+
})
6869
.finally(() => {
6970
started = true
7071
startPromise = undefined

packages/browser/src/client/vite.config.ts

+1-10
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,10 @@ export default defineConfig({
2222
orchestrator: resolve(__dirname, './orchestrator.html'),
2323
tester: resolve(__dirname, './tester/tester.html'),
2424
},
25-
external: [/__virtual_vitest__/, '@vitest/browser/context'],
25+
external: [/^vitest\//, 'vitest', /^msw/, '@vitest/browser/context'],
2626
},
2727
},
2828
plugins: [
29-
{
30-
name: 'virtual:msw',
31-
enforce: 'pre',
32-
resolveId(id) {
33-
if (id.startsWith('msw') || id.startsWith('vitest') || id.startsWith('@vitest/browser')) {
34-
return `/__virtual_vitest__?id=${encodeURIComponent(id)}`
35-
}
36-
},
37-
},
3829
{
3930
name: 'copy-ui-plugin',
4031
/* eslint-disable no-console */

packages/browser/src/node/plugin.ts

-14
Original file line numberDiff line numberDiff line change
@@ -220,20 +220,6 @@ export default (browserServer: BrowserServer, base = '/'): Plugin[] => {
220220
{
221221
name: 'vitest:browser:resolve-virtual',
222222
async resolveId(rawId) {
223-
if (rawId.startsWith('/__virtual_vitest__')) {
224-
const url = new URL(rawId, 'http://localhost')
225-
if (!url.searchParams.has('id')) {
226-
return
227-
}
228-
229-
const id = decodeURIComponent(url.searchParams.get('id')!)
230-
231-
const resolved = await this.resolve(id, distRoot, {
232-
skipSelf: true,
233-
})
234-
return resolved
235-
}
236-
237223
if (rawId === '/__vitest_msw__') {
238224
return this.resolve('msw/mockServiceWorker.js', distRoot, {
239225
skipSelf: true,

packages/browser/src/node/server.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ export class BrowserServer implements IBrowserServer {
182182
})
183183
}
184184

185-
private cdpSessions = new Map<string, Promise<CDPSession>>()
185+
private cdpSessionsPromises = new Map<string, Promise<CDPSession>>()
186186

187187
async ensureCDPHandler(contextId: string, sessionId: string) {
188188
const cachedHandler = this.state.cdps.get(sessionId)
@@ -195,11 +195,11 @@ export class BrowserServer implements IBrowserServer {
195195
throw new Error(`CDP is not supported by the provider "${provider.name}".`)
196196
}
197197

198-
const promise = this.cdpSessions.get(sessionId) ?? await (async () => {
198+
const promise = this.cdpSessionsPromises.get(sessionId) ?? await (async () => {
199199
const promise = provider.getCDPSession!(contextId).finally(() => {
200-
this.cdpSessions.delete(sessionId)
200+
this.cdpSessionsPromises.delete(sessionId)
201201
})
202-
this.cdpSessions.set(sessionId, promise)
202+
this.cdpSessionsPromises.set(sessionId, promise)
203203
return promise
204204
})()
205205

0 commit comments

Comments
 (0)