Skip to content

Commit abf536f

Browse files
authored
perf: more regex improvements (#12520)
1 parent 45549e4 commit abf536f

File tree

11 files changed

+73
-36
lines changed

11 files changed

+73
-36
lines changed

packages/vite/scripts/util.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ export function rewriteImports(
1717
})
1818
}
1919

20+
const windowsSlashRE = /\\/g
2021
export function slash(p: string): string {
21-
return p.replace(/\\/g, '/')
22+
return p.replace(windowsSlashRE, '/')
2223
}
2324

2425
export function walkDir(dir: string, handleFile: (file: string) => void): void {

packages/vite/src/node/optimizer/esbuildDepPlugin.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { CSS_LANGS_RE, KNOWN_ASSET_TYPES } from '../constants'
44
import { getDepOptimizationConfig } from '..'
55
import type { PackageCache, ResolvedConfig } from '..'
66
import {
7+
escapeRegex,
78
flattenId,
89
isBuiltin,
910
isExternalUrl,
@@ -281,6 +282,8 @@ module.exports = Object.create(new Proxy({}, {
281282
}
282283
}
283284

285+
const matchesEntireLine = (text: string) => `^${escapeRegex(text)}$`
286+
284287
// esbuild doesn't transpile `require('foo')` into `import` statements if 'foo' is externalized
285288
// https://github.com/evanw/esbuild/issues/566#issuecomment-735551834
286289
export function esbuildCjsExternalPlugin(
@@ -290,9 +293,7 @@ export function esbuildCjsExternalPlugin(
290293
return {
291294
name: 'cjs-external',
292295
setup(build) {
293-
const escape = (text: string) =>
294-
`^${text.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}$`
295-
const filter = new RegExp(externals.map(escape).join('|'))
296+
const filter = new RegExp(externals.map(matchesEntireLine).join('|'))
296297

297298
build.onResolve({ filter: new RegExp(`^${nonFacadePrefix}`) }, (args) => {
298299
return {

packages/vite/src/node/optimizer/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
normalizeId,
2222
normalizePath,
2323
removeDir,
24+
removeLeadingSlash,
2425
renameDir,
2526
writeFile,
2627
} from '../utils'
@@ -41,6 +42,7 @@ const isDebugEnabled = _debug('vite:deps').enabled
4142

4243
const jsExtensionRE = /\.js$/i
4344
const jsMapExtensionRE = /\.js\.map$/i
45+
const reExportRE = /export\s+\*\s+from/
4446

4547
export type ExportsData = {
4648
hasImports: boolean
@@ -956,7 +958,7 @@ export function createIsOptimizedDepUrl(
956958
const depsCacheDirPrefix = depsCacheDirRelative.startsWith('../')
957959
? // if the cache directory is outside root, the url prefix would be something
958960
// like '/@fs/absolute/path/to/node_modules/.vite'
959-
`/@fs/${normalizePath(depsCacheDir).replace(/^\//, '')}`
961+
`/@fs/${removeLeadingSlash(normalizePath(depsCacheDir))}`
960962
: // if the cache directory is inside root, the url prefix would be something
961963
// like '/node_modules/.vite'
962964
`/${depsCacheDirRelative}`
@@ -1140,7 +1142,7 @@ export async function extractExportsData(
11401142
facade,
11411143
hasReExports: imports.some(({ ss, se }) => {
11421144
const exp = entryContent.slice(ss, se)
1143-
return /export\s+\*\s+from/.test(exp)
1145+
return reExportRE.test(exp)
11441146
}),
11451147
jsxLoader: usedJsxLoader,
11461148
}

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,21 @@ import {
1616
} from '../build'
1717
import type { Plugin } from '../plugin'
1818
import type { ResolvedConfig } from '../config'
19-
import { cleanUrl, getHash, joinUrlSegments, normalizePath } from '../utils'
19+
import {
20+
cleanUrl,
21+
getHash,
22+
joinUrlSegments,
23+
normalizePath,
24+
removeLeadingSlash,
25+
} from '../utils'
2026
import { FS_PREFIX } from '../constants'
2127

2228
export const assetUrlRE = /__VITE_ASSET__([a-z\d]+)__(?:\$_(.*?)__)?/g
2329

2430
const rawRE = /(?:\?|&)raw(?:&|$)/
2531
const urlRE = /(\?|&)url(?:&|$)/
2632
const jsSourceMapRE = /\.[cm]?js\.map$/
33+
const unnededFinalQueryCharRE = /[?&]$/
2734

2835
const assetCache = new WeakMap<ResolvedConfig, Map<string, string>>()
2936

@@ -169,7 +176,7 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
169176
return
170177
}
171178

172-
id = id.replace(urlRE, '$1').replace(/[?&]$/, '')
179+
id = id.replace(urlRE, '$1').replace(unnededFinalQueryCharRE, '')
173180
const url = await fileToUrl(id, config, this)
174181
return `export default ${JSON.stringify(url)}`
175182
},
@@ -255,7 +262,7 @@ function fileToDevUrl(id: string, config: ResolvedConfig) {
255262
rtn = path.posix.join(FS_PREFIX, id)
256263
}
257264
const base = joinUrlSegments(config.server?.origin ?? '', config.base)
258-
return joinUrlSegments(base, rtn.replace(/^\//, ''))
265+
return joinUrlSegments(base, removeLeadingSlash(rtn))
259266
}
260267

261268
export function getPublicAssetFilename(

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import type { ResolvedConfig } from '../config'
44
import { CLIENT_ENTRY, ENV_ENTRY } from '../constants'
55
import { isObject, normalizePath, resolveHostname } from '../utils'
66

7+
const process_env_NODE_ENV_RE =
8+
/(\bglobal(This)?\.)?\bprocess\.env\.NODE_ENV\b/g
9+
710
// ids in transform are normalized to unix style
811
const normalizedClientEntry = normalizePath(CLIENT_ENTRY)
912
const normalizedEnvEntry = normalizePath(ENV_ENTRY)
@@ -86,7 +89,7 @@ export function clientInjectionsPlugin(config: ResolvedConfig): Plugin {
8689
// for it to avoid shimming a `process` object during dev,
8790
// avoiding inconsistencies between dev and build
8891
return code.replace(
89-
/(\bglobal(This)?\.)?\bprocess\.env\.NODE_ENV\b/g,
92+
process_env_NODE_ENV_RE,
9093
config.define?.['process.env.NODE_ENV'] ||
9194
JSON.stringify(process.env.NODE_ENV || config.mode),
9295
)

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import MagicString from 'magic-string'
22
import type { ResolvedConfig } from '../config'
33
import type { Plugin } from '../plugin'
4-
import { transformStableResult } from '../utils'
4+
import { escapeRegex, transformStableResult } from '../utils'
55
import { isCSSRequest } from './css'
66
import { isHTMLRequest } from './html'
77

@@ -113,11 +113,7 @@ export function definePlugin(config: ResolvedConfig): Plugin {
113113
// Mustn't be preceded by a char that can be part of an identifier
114114
// or a '.' that isn't part of a spread operator
115115
'(?<![\\p{L}\\p{N}_$]|(?<!\\.\\.)\\.)(' +
116-
replacementsKeys
117-
.map((str) => {
118-
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&')
119-
})
120-
.join('|') +
116+
replacementsKeys.map(escapeRegex).join('|') +
121117
// Mustn't be followed by a char that can be part of an identifier
122118
// or an assignment (but allow equality operators)
123119
')(?:(?<=\\.)|(?![\\p{L}\\p{N}_$]|\\s*?=[^=]))',

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
isExternalUrl,
2121
normalizePath,
2222
processSrcSet,
23+
removeLeadingSlash,
2324
} from '../utils'
2425
import type { ResolvedConfig } from '../config'
2526
import { toOutputFilePathInHtml } from '../build'
@@ -537,7 +538,7 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
537538
if (
538539
content !== '' && // Empty attribute
539540
!namedOutput.includes(content) && // Direct reference to named output
540-
!namedOutput.includes(content.replace(/^\//, '')) // Allow for absolute references as named output can't be an absolute path
541+
!namedOutput.includes(removeLeadingSlash(content)) // Allow for absolute references as named output can't be an absolute path
541542
) {
542543
try {
543544
const url =

packages/vite/src/node/server/__tests__/pluginContainer.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ async function getPluginContainer(
196196
)
197197

198198
// @ts-expect-error This plugin requires a ViteDevServer instance.
199-
config.plugins = config.plugins.filter((p) => !/pre-alias/.test(p.name))
199+
config.plugins = config.plugins.filter((p) => !p.name.includes('pre-alias'))
200200

201201
resolveId = (id) => container.resolveId(id)
202202
const container = await createPluginContainer(config, moduleGraph)

packages/vite/src/node/server/hmr.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import type { ModuleNode } from './moduleGraph'
1414

1515
export const debugHmr = createDebugger('vite:hmr')
1616

17+
const whitespaceRE = /\s/
18+
1719
const normalizedClientDir = normalizePath(CLIENT_DIR)
1820

1921
export interface HmrOptions {
@@ -388,7 +390,7 @@ export function lexAcceptedHmrDeps(
388390
} else if (char === '`') {
389391
prevState = state
390392
state = LexerState.inTemplateString
391-
} else if (/\s/.test(char)) {
393+
} else if (whitespaceRE.test(char)) {
392394
continue
393395
} else {
394396
if (state === LexerState.inCall) {

packages/vite/src/node/server/middlewares/static.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@ import {
1414
isInternalRequest,
1515
isParentDirectory,
1616
isWindows,
17+
removeLeadingSlash,
1718
shouldServeFile,
1819
slash,
1920
} from '../../utils'
2021

22+
const knownJavascriptExtensionRE = /\.[tj]sx?$/
23+
2124
const sirvOptions = ({
2225
headers,
2326
shouldServe,
@@ -35,7 +38,7 @@ const sirvOptions = ({
3538
// for the MIME type video/mp2t. In almost all cases, we can expect
3639
// these files to be TypeScript files, and for Vite to serve them with
3740
// this Content-Type.
38-
if (/\.[tj]sx?$/.test(pathname)) {
41+
if (knownJavascriptExtensionRE.test(pathname)) {
3942
res.setHeader('Content-Type', 'application/javascript')
4043
}
4144
if (headers) {
@@ -119,7 +122,7 @@ export function serveStaticMiddleware(
119122
}
120123

121124
const resolvedPathname = redirectedPathname || pathname
122-
let fileUrl = path.resolve(dir, resolvedPathname.replace(/^\//, ''))
125+
let fileUrl = path.resolve(dir, removeLeadingSlash(resolvedPathname))
123126
if (resolvedPathname.endsWith('/') && !fileUrl.endsWith('/')) {
124127
fileUrl = fileUrl + '/'
125128
}

0 commit comments

Comments
 (0)