Skip to content

Commit 0cacfad

Browse files
authored
perf: avoid parseRequest (#15617)
1 parent bdb826c commit 0cacfad

File tree

7 files changed

+61
-78
lines changed

7 files changed

+61
-78
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3-
exports[`parse positives > ? in url 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mo\\\\?ds/*.js", {"query":"url","import":"*"})), \`./mo?ds/\${base ?? foo}.js\`)"`;
3+
exports[`parse positives > ? in url 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mo\\\\?ds/*.js", {"query":"?url","import":"*"})), \`./mo?ds/\${base ?? foo}.js\`)"`;
44
5-
exports[`parse positives > ? in variables 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"raw","import":"*"})), \`./mods/\${base ?? foo}.js\`)"`;
5+
exports[`parse positives > ? in variables 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"?raw","import":"*"})), \`./mods/\${base ?? foo}.js\`)"`;
66
7-
exports[`parse positives > ? in worker 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mo\\\\?ds/*.js", {"query":"worker","import":"*"})), \`./mo?ds/\${base ?? foo}.js\`)"`;
7+
exports[`parse positives > ? in worker 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mo\\\\?ds/*.js", {"query":"?worker","import":"*"})), \`./mo?ds/\${base ?? foo}.js\`)"`;
88
99
exports[`parse positives > alias path 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js")), \`./mods/\${base}.js\`)"`;
1010
@@ -14,8 +14,8 @@ exports[`parse positives > with ../ and itself 1`] = `"__variableDynamicImportRu
1414
1515
exports[`parse positives > with multi ../ and itself 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("../../plugins/dynamicImportVar/*.js")), \`./\${name}.js\`)"`;
1616
17-
exports[`parse positives > with query 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":{"foo":"bar"}})), \`./mods/\${base}.js\`)"`;
17+
exports[`parse positives > with query 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"?foo=bar"})), \`./mods/\${base}.js\`)"`;
1818
19-
exports[`parse positives > with query raw 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"raw","import":"*"})), \`./mods/\${base}.js\`)"`;
19+
exports[`parse positives > with query raw 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"?raw","import":"*"})), \`./mods/\${base}.js\`)"`;
2020
21-
exports[`parse positives > with query url 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"url","import":"*"})), \`./mods/\${base}.js\`)"`;
21+
exports[`parse positives > with query url 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"?url","import":"*"})), \`./mods/\${base}.js\`)"`;

packages/vite/src/node/plugins/css.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ import {
5858
isObject,
5959
joinUrlSegments,
6060
normalizePath,
61-
parseRequest,
6261
processSrcSet,
6362
removeDirectQuery,
6463
removeUrlQuery,
@@ -171,6 +170,7 @@ export function resolveCSSOptions(
171170
const cssModuleRE = new RegExp(`\\.module${CSS_LANGS_RE.source}`)
172171
const directRequestRE = /[?&]direct\b/
173172
const htmlProxyRE = /[?&]html-proxy\b/
173+
const htmlProxyIndexRE = /&index=(\d+)/
174174
const commonjsProxyRE = /\?commonjs-proxy/
175175
const inlineRE = /[?&]inline\b/
176176
const inlineCSSRE = /[?&]inline-css\b/
@@ -474,12 +474,15 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
474474
const inlineCSS = inlineCSSRE.test(id)
475475
const isHTMLProxy = htmlProxyRE.test(id)
476476
if (inlineCSS && isHTMLProxy) {
477-
const query = parseRequest(id)
478477
if (styleAttrRE.test(id)) {
479478
css = css.replace(/"/g, '"')
480479
}
480+
const index = htmlProxyIndexRE.exec(id)?.[1]
481+
if (index == null) {
482+
throw new Error(`HTML proxy index in "${id}" not found`)
483+
}
481484
addToHTMLProxyTransformResult(
482-
`${getHash(cleanUrl(id))}_${Number.parseInt(query!.index)}`,
485+
`${getHash(cleanUrl(id))}_${Number.parseInt(index)}`,
483486
css,
484487
)
485488
return `export default ''`

packages/vite/src/node/plugins/dynamicImportVars.ts

+20-17
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ import { CLIENT_ENTRY } from '../constants'
1010
import {
1111
createFilter,
1212
normalizePath,
13-
parseRequest,
13+
rawRE,
1414
requestQueryMaybeEscapedSplitRE,
1515
requestQuerySplitRE,
1616
transformStableResult,
17+
urlRE,
1718
} from '../utils'
1819
import { toAbsoluteGlob } from './importMetaGlob'
1920
import { hasViteIgnoreRE } from './importAnalysis'
21+
import { workerOrSharedWorkerRE } from './worker'
2022

2123
export const dynamicImportHelperId = '\0vite/dynamic-import-helper.js'
2224

@@ -53,9 +55,6 @@ function parseDynamicImportPattern(
5355
strings: string,
5456
): DynamicImportPattern | null {
5557
const filename = strings.slice(1, -1)
56-
const rawQuery = parseRequest(filename)
57-
let globParams: DynamicImportRequest | null = null
58-
5958
const ast = (
6059
parseJS(strings, {
6160
ecmaVersion: 'latest',
@@ -73,19 +72,23 @@ function parseDynamicImportPattern(
7372
requestQueryMaybeEscapedSplitRE,
7473
2,
7574
)
76-
const [rawPattern] = filename.split(requestQuerySplitRE, 2)
77-
78-
const globQuery = (['worker', 'url', 'raw'] as const).find(
79-
(key) => rawQuery && key in rawQuery,
80-
)
81-
if (globQuery) {
82-
globParams = {
83-
query: globQuery,
84-
import: '*',
85-
}
86-
} else if (rawQuery) {
87-
globParams = {
88-
query: rawQuery,
75+
let [rawPattern, search] = filename.split(requestQuerySplitRE, 2)
76+
let globParams: DynamicImportRequest | null = null
77+
if (search) {
78+
search = '?' + search
79+
if (
80+
workerOrSharedWorkerRE.test(search) ||
81+
urlRE.test(search) ||
82+
rawRE.test(search)
83+
) {
84+
globParams = {
85+
query: search,
86+
import: '*',
87+
}
88+
} else {
89+
globParams = {
90+
query: search,
91+
}
8992
}
9093
}
9194

packages/vite/src/node/plugins/worker.ts

+22-37
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { ResolvedConfig } from '../config'
55
import type { Plugin } from '../plugin'
66
import type { ViteDevServer } from '../server'
77
import { ENV_ENTRY, ENV_PUBLIC_PATH } from '../constants'
8-
import { cleanUrl, getHash, injectQuery, parseRequest } from '../utils'
8+
import { cleanUrl, getHash, injectQuery, urlRE } from '../utils'
99
import {
1010
createToImportMetaURLBasedRelativeRuntime,
1111
onRollupWarning,
@@ -28,6 +28,10 @@ interface WorkerCache {
2828

2929
export type WorkerType = 'classic' | 'module' | 'ignore'
3030

31+
export const workerOrSharedWorkerRE = /(?:\?|&)(worker|sharedworker)(?:&|$)/
32+
const workerFileRE = /(?:\?|&)worker_file&type=(\w+)(?:&|$)/
33+
const inlineRE = /[?&]inline\b/
34+
3135
export const WORKER_FILE_ID = 'worker_file'
3236
const workerCache = new WeakMap<ResolvedConfig, WorkerCache>()
3337

@@ -43,7 +47,6 @@ function saveEmitWorkerAsset(
4347
async function bundleWorkerEntry(
4448
config: ResolvedConfig,
4549
id: string,
46-
query: Record<string, string> | null,
4750
): Promise<OutputChunk> {
4851
// bundle the file as entry to support imports
4952
const { rollup } = await import('rollup')
@@ -99,12 +102,11 @@ async function bundleWorkerEntry(
99102
} finally {
100103
await bundle.close()
101104
}
102-
return emitSourcemapForWorkerEntry(config, query, chunk)
105+
return emitSourcemapForWorkerEntry(config, chunk)
103106
}
104107

105108
function emitSourcemapForWorkerEntry(
106109
config: ResolvedConfig,
107-
query: Record<string, string> | null,
108110
chunk: OutputChunk,
109111
): OutputChunk {
110112
const { map: sourcemap } = chunk
@@ -144,12 +146,11 @@ function encodeWorkerAssetFileName(
144146
export async function workerFileToUrl(
145147
config: ResolvedConfig,
146148
id: string,
147-
query: Record<string, string> | null,
148149
): Promise<string> {
149150
const workerMap = workerCache.get(config.mainConfig || config)!
150151
let fileName = workerMap.bundle.get(id)
151152
if (!fileName) {
152-
const outputChunk = await bundleWorkerEntry(config, id, query)
153+
const outputChunk = await bundleWorkerEntry(config, id)
153154
fileName = outputChunk.fileName
154155
saveEmitWorkerAsset(config, {
155156
fileName,
@@ -191,18 +192,6 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
191192
let server: ViteDevServer
192193
const isWorker = config.isWorker
193194

194-
const isWorkerQueryId = (id: string) => {
195-
const parsedQuery = parseRequest(id)
196-
if (
197-
parsedQuery &&
198-
(parsedQuery.worker ?? parsedQuery.sharedworker) != null
199-
) {
200-
return true
201-
}
202-
203-
return false
204-
}
205-
206195
return {
207196
name: 'vite:worker',
208197

@@ -222,23 +211,23 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
222211
},
223212

224213
load(id) {
225-
if (isBuild && isWorkerQueryId(id)) {
214+
if (isBuild && workerOrSharedWorkerRE.test(id)) {
226215
return ''
227216
}
228217
},
229218

230219
shouldTransformCachedModule({ id }) {
231-
if (isBuild && config.build.watch && isWorkerQueryId(id)) {
220+
if (isBuild && config.build.watch && workerOrSharedWorkerRE.test(id)) {
232221
return true
233222
}
234223
},
235224

236-
async transform(raw, id, options) {
237-
const query = parseRequest(id)
238-
if (query && query[WORKER_FILE_ID] != null) {
225+
async transform(raw, id) {
226+
const workerFileMatch = workerFileRE.exec(id)
227+
if (workerFileMatch) {
239228
// if import worker by worker constructor will have query.type
240229
// other type will be import worker by esm
241-
const workerType = query['type']! as WorkerType
230+
const workerType = workerFileMatch[1] as WorkerType
242231
let injectEnv = ''
243232

244233
const scriptPath = JSON.stringify(
@@ -270,18 +259,15 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
270259
}
271260
return
272261
}
273-
if (
274-
query == null ||
275-
(query && (query.worker ?? query.sharedworker) == null)
276-
) {
277-
return
278-
}
262+
263+
const workerMatch = workerOrSharedWorkerRE.exec(id)
264+
if (!workerMatch) return
279265

280266
// stringified url or `new URL(...)`
281267
let url: string
282268
const { format } = config.worker
283269
const workerConstructor =
284-
query.sharedworker != null ? 'SharedWorker' : 'Worker'
270+
workerMatch[1] === 'sharedworker' ? 'SharedWorker' : 'Worker'
285271
const workerType = isBuild
286272
? format === 'es'
287273
? 'module'
@@ -293,8 +279,8 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
293279
}`
294280

295281
if (isBuild) {
296-
if (query.inline != null) {
297-
const chunk = await bundleWorkerEntry(config, id, query)
282+
if (inlineRE.test(id)) {
283+
const chunk = await bundleWorkerEntry(config, id)
298284
const encodedJs = `const encodedJs = "${Buffer.from(
299285
chunk.code,
300286
).toString('base64')}";`
@@ -349,15 +335,14 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
349335
map: { mappings: '' },
350336
}
351337
} else {
352-
url = await workerFileToUrl(config, id, query)
338+
url = await workerFileToUrl(config, id)
353339
}
354340
} else {
355341
url = await fileToUrl(cleanUrl(id), config, this)
356-
url = injectQuery(url, WORKER_FILE_ID)
357-
url = injectQuery(url, `type=${workerType}`)
342+
url = injectQuery(url, `${WORKER_FILE_ID}&type=${workerType}`)
358343
}
359344

360-
if (query.url != null) {
345+
if (urlRE.test(id)) {
361346
return {
362347
code: `export default ${JSON.stringify(url)}`,
363348
map: { mappings: '' }, // Empty sourcemap to suppress Rollup warning

packages/vite/src/node/plugins/workerImportMetaUrl.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
cleanUrl,
99
evalValue,
1010
injectQuery,
11-
parseRequest,
1211
slash,
1312
transformStableResult,
1413
} from '../utils'
@@ -131,7 +130,6 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
131130

132131
async transform(code, id, options) {
133132
if (!options?.ssr && isIncludeWorkerImportMetaUrl(code)) {
134-
const query = parseRequest(id)
135133
let s: MagicString | undefined
136134
const cleanString = stripLiteral(code)
137135
const workerImportMetaUrlRE =
@@ -174,11 +172,13 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
174172

175173
let builtUrl: string
176174
if (isBuild) {
177-
builtUrl = await workerFileToUrl(config, file, query)
175+
builtUrl = await workerFileToUrl(config, file)
178176
} else {
179177
builtUrl = await fileToUrl(cleanUrl(file), config, this)
180-
builtUrl = injectQuery(builtUrl, WORKER_FILE_ID)
181-
builtUrl = injectQuery(builtUrl, `type=${workerType}`)
178+
builtUrl = injectQuery(
179+
builtUrl,
180+
`${WORKER_FILE_ID}&type=${workerType}`,
181+
)
182182
}
183183
s.update(
184184
expStart,

packages/vite/src/node/utils.ts

+1-9
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import os from 'node:os'
33
import path from 'node:path'
44
import { exec } from 'node:child_process'
55
import { createHash } from 'node:crypto'
6-
import { URL, URLSearchParams, fileURLToPath } from 'node:url'
6+
import { URL, fileURLToPath } from 'node:url'
77
import { builtinModules, createRequire } from 'node:module'
88
import { promises as dns } from 'node:dns'
99
import { performance } from 'node:perf_hooks'
@@ -1041,14 +1041,6 @@ export const singlelineCommentsRE = /\/\/.*/g
10411041
export const requestQuerySplitRE = /\?(?!.*[/|}])/
10421042
export const requestQueryMaybeEscapedSplitRE = /\\?\?(?!.*[/|}])/
10431043

1044-
export function parseRequest(id: string): Record<string, string> | null {
1045-
const [_, search] = id.split(requestQuerySplitRE, 2)
1046-
if (!search) {
1047-
return null
1048-
}
1049-
return Object.fromEntries(new URLSearchParams(search))
1050-
}
1051-
10521044
export const blankReplacer = (match: string): string => ' '.repeat(match.length)
10531045

10541046
export function getHash(text: Buffer | string, length = 8): string {

playground/worker/__tests__/iife/iife-worker.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ test('import.meta.glob eager in worker', async () => {
161161
})
162162

163163
test.runIf(isServe)('sourcemap boundary', async () => {
164-
const response = page.waitForResponse(/my-worker.ts\?type=module&worker_file/)
164+
const response = page.waitForResponse(/my-worker.ts\?worker_file&type=module/)
165165
await page.goto(viteTestUrl)
166166
const content = await (await response).text()
167167
const { mappings } = decodeSourceMapUrl(content)

0 commit comments

Comments
 (0)