mirror of
https://github.com/vitejs/vite.git
synced 2024-11-21 22:59:10 +00:00
perf: avoid parseRequest (#15617)
This commit is contained in:
parent
bdb826ca0a
commit
0cacfadf3a
@ -1,10 +1,10 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`parse positives > ? in url 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mo\\\\?ds/*.js", {"query":"url","import":"*"})), \`./mo?ds/\${base ?? foo}.js\`)"`;
|
||||
exports[`parse positives > ? in url 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mo\\\\?ds/*.js", {"query":"?url","import":"*"})), \`./mo?ds/\${base ?? foo}.js\`)"`;
|
||||
|
||||
exports[`parse positives > ? in variables 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"raw","import":"*"})), \`./mods/\${base ?? foo}.js\`)"`;
|
||||
exports[`parse positives > ? in variables 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"?raw","import":"*"})), \`./mods/\${base ?? foo}.js\`)"`;
|
||||
|
||||
exports[`parse positives > ? in worker 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mo\\\\?ds/*.js", {"query":"worker","import":"*"})), \`./mo?ds/\${base ?? foo}.js\`)"`;
|
||||
exports[`parse positives > ? in worker 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mo\\\\?ds/*.js", {"query":"?worker","import":"*"})), \`./mo?ds/\${base ?? foo}.js\`)"`;
|
||||
|
||||
exports[`parse positives > alias path 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js")), \`./mods/\${base}.js\`)"`;
|
||||
|
||||
@ -14,8 +14,8 @@ exports[`parse positives > with ../ and itself 1`] = `"__variableDynamicImportRu
|
||||
|
||||
exports[`parse positives > with multi ../ and itself 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("../../plugins/dynamicImportVar/*.js")), \`./\${name}.js\`)"`;
|
||||
|
||||
exports[`parse positives > with query 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":{"foo":"bar"}})), \`./mods/\${base}.js\`)"`;
|
||||
exports[`parse positives > with query 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"?foo=bar"})), \`./mods/\${base}.js\`)"`;
|
||||
|
||||
exports[`parse positives > with query raw 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"raw","import":"*"})), \`./mods/\${base}.js\`)"`;
|
||||
exports[`parse positives > with query raw 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"?raw","import":"*"})), \`./mods/\${base}.js\`)"`;
|
||||
|
||||
exports[`parse positives > with query url 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"url","import":"*"})), \`./mods/\${base}.js\`)"`;
|
||||
exports[`parse positives > with query url 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob("./mods/*.js", {"query":"?url","import":"*"})), \`./mods/\${base}.js\`)"`;
|
||||
|
@ -58,7 +58,6 @@ import {
|
||||
isObject,
|
||||
joinUrlSegments,
|
||||
normalizePath,
|
||||
parseRequest,
|
||||
processSrcSet,
|
||||
removeDirectQuery,
|
||||
removeUrlQuery,
|
||||
@ -171,6 +170,7 @@ export function resolveCSSOptions(
|
||||
const cssModuleRE = new RegExp(`\\.module${CSS_LANGS_RE.source}`)
|
||||
const directRequestRE = /[?&]direct\b/
|
||||
const htmlProxyRE = /[?&]html-proxy\b/
|
||||
const htmlProxyIndexRE = /&index=(\d+)/
|
||||
const commonjsProxyRE = /\?commonjs-proxy/
|
||||
const inlineRE = /[?&]inline\b/
|
||||
const inlineCSSRE = /[?&]inline-css\b/
|
||||
@ -474,12 +474,15 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
|
||||
const inlineCSS = inlineCSSRE.test(id)
|
||||
const isHTMLProxy = htmlProxyRE.test(id)
|
||||
if (inlineCSS && isHTMLProxy) {
|
||||
const query = parseRequest(id)
|
||||
if (styleAttrRE.test(id)) {
|
||||
css = css.replace(/"/g, '"')
|
||||
}
|
||||
const index = htmlProxyIndexRE.exec(id)?.[1]
|
||||
if (index == null) {
|
||||
throw new Error(`HTML proxy index in "${id}" not found`)
|
||||
}
|
||||
addToHTMLProxyTransformResult(
|
||||
`${getHash(cleanUrl(id))}_${Number.parseInt(query!.index)}`,
|
||||
`${getHash(cleanUrl(id))}_${Number.parseInt(index)}`,
|
||||
css,
|
||||
)
|
||||
return `export default ''`
|
||||
|
@ -10,13 +10,15 @@ import { CLIENT_ENTRY } from '../constants'
|
||||
import {
|
||||
createFilter,
|
||||
normalizePath,
|
||||
parseRequest,
|
||||
rawRE,
|
||||
requestQueryMaybeEscapedSplitRE,
|
||||
requestQuerySplitRE,
|
||||
transformStableResult,
|
||||
urlRE,
|
||||
} from '../utils'
|
||||
import { toAbsoluteGlob } from './importMetaGlob'
|
||||
import { hasViteIgnoreRE } from './importAnalysis'
|
||||
import { workerOrSharedWorkerRE } from './worker'
|
||||
|
||||
export const dynamicImportHelperId = '\0vite/dynamic-import-helper.js'
|
||||
|
||||
@ -53,9 +55,6 @@ function parseDynamicImportPattern(
|
||||
strings: string,
|
||||
): DynamicImportPattern | null {
|
||||
const filename = strings.slice(1, -1)
|
||||
const rawQuery = parseRequest(filename)
|
||||
let globParams: DynamicImportRequest | null = null
|
||||
|
||||
const ast = (
|
||||
parseJS(strings, {
|
||||
ecmaVersion: 'latest',
|
||||
@ -73,19 +72,23 @@ function parseDynamicImportPattern(
|
||||
requestQueryMaybeEscapedSplitRE,
|
||||
2,
|
||||
)
|
||||
const [rawPattern] = filename.split(requestQuerySplitRE, 2)
|
||||
|
||||
const globQuery = (['worker', 'url', 'raw'] as const).find(
|
||||
(key) => rawQuery && key in rawQuery,
|
||||
)
|
||||
if (globQuery) {
|
||||
globParams = {
|
||||
query: globQuery,
|
||||
import: '*',
|
||||
}
|
||||
} else if (rawQuery) {
|
||||
globParams = {
|
||||
query: rawQuery,
|
||||
let [rawPattern, search] = filename.split(requestQuerySplitRE, 2)
|
||||
let globParams: DynamicImportRequest | null = null
|
||||
if (search) {
|
||||
search = '?' + search
|
||||
if (
|
||||
workerOrSharedWorkerRE.test(search) ||
|
||||
urlRE.test(search) ||
|
||||
rawRE.test(search)
|
||||
) {
|
||||
globParams = {
|
||||
query: search,
|
||||
import: '*',
|
||||
}
|
||||
} else {
|
||||
globParams = {
|
||||
query: search,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import type { ResolvedConfig } from '../config'
|
||||
import type { Plugin } from '../plugin'
|
||||
import type { ViteDevServer } from '../server'
|
||||
import { ENV_ENTRY, ENV_PUBLIC_PATH } from '../constants'
|
||||
import { cleanUrl, getHash, injectQuery, parseRequest } from '../utils'
|
||||
import { cleanUrl, getHash, injectQuery, urlRE } from '../utils'
|
||||
import {
|
||||
createToImportMetaURLBasedRelativeRuntime,
|
||||
onRollupWarning,
|
||||
@ -28,6 +28,10 @@ interface WorkerCache {
|
||||
|
||||
export type WorkerType = 'classic' | 'module' | 'ignore'
|
||||
|
||||
export const workerOrSharedWorkerRE = /(?:\?|&)(worker|sharedworker)(?:&|$)/
|
||||
const workerFileRE = /(?:\?|&)worker_file&type=(\w+)(?:&|$)/
|
||||
const inlineRE = /[?&]inline\b/
|
||||
|
||||
export const WORKER_FILE_ID = 'worker_file'
|
||||
const workerCache = new WeakMap<ResolvedConfig, WorkerCache>()
|
||||
|
||||
@ -43,7 +47,6 @@ function saveEmitWorkerAsset(
|
||||
async function bundleWorkerEntry(
|
||||
config: ResolvedConfig,
|
||||
id: string,
|
||||
query: Record<string, string> | null,
|
||||
): Promise<OutputChunk> {
|
||||
// bundle the file as entry to support imports
|
||||
const { rollup } = await import('rollup')
|
||||
@ -99,12 +102,11 @@ async function bundleWorkerEntry(
|
||||
} finally {
|
||||
await bundle.close()
|
||||
}
|
||||
return emitSourcemapForWorkerEntry(config, query, chunk)
|
||||
return emitSourcemapForWorkerEntry(config, chunk)
|
||||
}
|
||||
|
||||
function emitSourcemapForWorkerEntry(
|
||||
config: ResolvedConfig,
|
||||
query: Record<string, string> | null,
|
||||
chunk: OutputChunk,
|
||||
): OutputChunk {
|
||||
const { map: sourcemap } = chunk
|
||||
@ -144,12 +146,11 @@ function encodeWorkerAssetFileName(
|
||||
export async function workerFileToUrl(
|
||||
config: ResolvedConfig,
|
||||
id: string,
|
||||
query: Record<string, string> | null,
|
||||
): Promise<string> {
|
||||
const workerMap = workerCache.get(config.mainConfig || config)!
|
||||
let fileName = workerMap.bundle.get(id)
|
||||
if (!fileName) {
|
||||
const outputChunk = await bundleWorkerEntry(config, id, query)
|
||||
const outputChunk = await bundleWorkerEntry(config, id)
|
||||
fileName = outputChunk.fileName
|
||||
saveEmitWorkerAsset(config, {
|
||||
fileName,
|
||||
@ -191,18 +192,6 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
|
||||
let server: ViteDevServer
|
||||
const isWorker = config.isWorker
|
||||
|
||||
const isWorkerQueryId = (id: string) => {
|
||||
const parsedQuery = parseRequest(id)
|
||||
if (
|
||||
parsedQuery &&
|
||||
(parsedQuery.worker ?? parsedQuery.sharedworker) != null
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'vite:worker',
|
||||
|
||||
@ -222,23 +211,23 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
|
||||
},
|
||||
|
||||
load(id) {
|
||||
if (isBuild && isWorkerQueryId(id)) {
|
||||
if (isBuild && workerOrSharedWorkerRE.test(id)) {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
|
||||
shouldTransformCachedModule({ id }) {
|
||||
if (isBuild && config.build.watch && isWorkerQueryId(id)) {
|
||||
if (isBuild && config.build.watch && workerOrSharedWorkerRE.test(id)) {
|
||||
return true
|
||||
}
|
||||
},
|
||||
|
||||
async transform(raw, id, options) {
|
||||
const query = parseRequest(id)
|
||||
if (query && query[WORKER_FILE_ID] != null) {
|
||||
async transform(raw, id) {
|
||||
const workerFileMatch = workerFileRE.exec(id)
|
||||
if (workerFileMatch) {
|
||||
// if import worker by worker constructor will have query.type
|
||||
// other type will be import worker by esm
|
||||
const workerType = query['type']! as WorkerType
|
||||
const workerType = workerFileMatch[1] as WorkerType
|
||||
let injectEnv = ''
|
||||
|
||||
const scriptPath = JSON.stringify(
|
||||
@ -270,18 +259,15 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
|
||||
}
|
||||
return
|
||||
}
|
||||
if (
|
||||
query == null ||
|
||||
(query && (query.worker ?? query.sharedworker) == null)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const workerMatch = workerOrSharedWorkerRE.exec(id)
|
||||
if (!workerMatch) return
|
||||
|
||||
// stringified url or `new URL(...)`
|
||||
let url: string
|
||||
const { format } = config.worker
|
||||
const workerConstructor =
|
||||
query.sharedworker != null ? 'SharedWorker' : 'Worker'
|
||||
workerMatch[1] === 'sharedworker' ? 'SharedWorker' : 'Worker'
|
||||
const workerType = isBuild
|
||||
? format === 'es'
|
||||
? 'module'
|
||||
@ -293,8 +279,8 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
|
||||
}`
|
||||
|
||||
if (isBuild) {
|
||||
if (query.inline != null) {
|
||||
const chunk = await bundleWorkerEntry(config, id, query)
|
||||
if (inlineRE.test(id)) {
|
||||
const chunk = await bundleWorkerEntry(config, id)
|
||||
const encodedJs = `const encodedJs = "${Buffer.from(
|
||||
chunk.code,
|
||||
).toString('base64')}";`
|
||||
@ -349,15 +335,14 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
|
||||
map: { mappings: '' },
|
||||
}
|
||||
} else {
|
||||
url = await workerFileToUrl(config, id, query)
|
||||
url = await workerFileToUrl(config, id)
|
||||
}
|
||||
} else {
|
||||
url = await fileToUrl(cleanUrl(id), config, this)
|
||||
url = injectQuery(url, WORKER_FILE_ID)
|
||||
url = injectQuery(url, `type=${workerType}`)
|
||||
url = injectQuery(url, `${WORKER_FILE_ID}&type=${workerType}`)
|
||||
}
|
||||
|
||||
if (query.url != null) {
|
||||
if (urlRE.test(id)) {
|
||||
return {
|
||||
code: `export default ${JSON.stringify(url)}`,
|
||||
map: { mappings: '' }, // Empty sourcemap to suppress Rollup warning
|
||||
|
@ -8,7 +8,6 @@ import {
|
||||
cleanUrl,
|
||||
evalValue,
|
||||
injectQuery,
|
||||
parseRequest,
|
||||
slash,
|
||||
transformStableResult,
|
||||
} from '../utils'
|
||||
@ -131,7 +130,6 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
|
||||
|
||||
async transform(code, id, options) {
|
||||
if (!options?.ssr && isIncludeWorkerImportMetaUrl(code)) {
|
||||
const query = parseRequest(id)
|
||||
let s: MagicString | undefined
|
||||
const cleanString = stripLiteral(code)
|
||||
const workerImportMetaUrlRE =
|
||||
@ -174,11 +172,13 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
|
||||
|
||||
let builtUrl: string
|
||||
if (isBuild) {
|
||||
builtUrl = await workerFileToUrl(config, file, query)
|
||||
builtUrl = await workerFileToUrl(config, file)
|
||||
} else {
|
||||
builtUrl = await fileToUrl(cleanUrl(file), config, this)
|
||||
builtUrl = injectQuery(builtUrl, WORKER_FILE_ID)
|
||||
builtUrl = injectQuery(builtUrl, `type=${workerType}`)
|
||||
builtUrl = injectQuery(
|
||||
builtUrl,
|
||||
`${WORKER_FILE_ID}&type=${workerType}`,
|
||||
)
|
||||
}
|
||||
s.update(
|
||||
expStart,
|
||||
|
@ -3,7 +3,7 @@ import os from 'node:os'
|
||||
import path from 'node:path'
|
||||
import { exec } from 'node:child_process'
|
||||
import { createHash } from 'node:crypto'
|
||||
import { URL, URLSearchParams, fileURLToPath } from 'node:url'
|
||||
import { URL, fileURLToPath } from 'node:url'
|
||||
import { builtinModules, createRequire } from 'node:module'
|
||||
import { promises as dns } from 'node:dns'
|
||||
import { performance } from 'node:perf_hooks'
|
||||
@ -1041,14 +1041,6 @@ export const singlelineCommentsRE = /\/\/.*/g
|
||||
export const requestQuerySplitRE = /\?(?!.*[/|}])/
|
||||
export const requestQueryMaybeEscapedSplitRE = /\\?\?(?!.*[/|}])/
|
||||
|
||||
export function parseRequest(id: string): Record<string, string> | null {
|
||||
const [_, search] = id.split(requestQuerySplitRE, 2)
|
||||
if (!search) {
|
||||
return null
|
||||
}
|
||||
return Object.fromEntries(new URLSearchParams(search))
|
||||
}
|
||||
|
||||
export const blankReplacer = (match: string): string => ' '.repeat(match.length)
|
||||
|
||||
export function getHash(text: Buffer | string, length = 8): string {
|
||||
|
@ -161,7 +161,7 @@ test('import.meta.glob eager in worker', async () => {
|
||||
})
|
||||
|
||||
test.runIf(isServe)('sourcemap boundary', async () => {
|
||||
const response = page.waitForResponse(/my-worker.ts\?type=module&worker_file/)
|
||||
const response = page.waitForResponse(/my-worker.ts\?worker_file&type=module/)
|
||||
await page.goto(viteTestUrl)
|
||||
const content = await (await response).text()
|
||||
const { mappings } = decodeSourceMapUrl(content)
|
||||
|
Loading…
Reference in New Issue
Block a user