From 68be9c7a5245e4aa4f8d2bd2909720d967aafae6 Mon Sep 17 00:00:00 2001 From: sapphi-red Date: Sun, 13 Nov 2022 22:44:44 +0900 Subject: [PATCH] perf: regex perf (super-linear-move) --- .eslintrc.cjs | 8 +- packages/create-vite/src/index.ts | 1 + packages/plugin-legacy/src/index.ts | 10 ++- packages/plugin-react/src/index.ts | 1 + packages/plugin-vue/src/main.ts | 7 +- packages/vite/src/client/client.ts | 10 ++- packages/vite/src/client/overlay.ts | 2 + packages/vite/src/node/optimizer/scan.ts | 1 + .../src/node/plugins/dynamicImportVars.ts | 6 +- packages/vite/src/node/plugins/ensureWatch.ts | 4 +- packages/vite/src/node/plugins/html.ts | 82 +++++++++++-------- .../vite/src/node/plugins/importAnalysis.ts | 1 + .../vite/src/node/plugins/importMetaGlob.ts | 10 ++- .../src/node/plugins/workerImportMetaUrl.ts | 1 + packages/vite/src/node/utils.ts | 36 ++++++-- 15 files changed, 127 insertions(+), 53 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 59a3579c80fc2e..76ceab570323e6 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -107,7 +107,13 @@ module.exports = defineConfig({ files: ['packages/**'], excludedFiles: '**/__tests__/**', rules: { - 'no-restricted-globals': ['error', 'require', '__dirname', '__filename'] + 'no-restricted-globals': [ + 'error', + 'require', + '__dirname', + '__filename' + ], + 'regexp/no-super-linear-move': 'error' } }, { diff --git a/packages/create-vite/src/index.ts b/packages/create-vite/src/index.ts index ce800f3eb23a24..247c807fb55516 100755 --- a/packages/create-vite/src/index.ts +++ b/packages/create-vite/src/index.ts @@ -375,6 +375,7 @@ async function init() { } function formatTargetDir(targetDir: string | undefined) { + // eslint-disable-next-line regexp/no-super-linear-move -- `targetDir` won't be so long return targetDir?.trim().replace(/\/+$/g, '') } diff --git a/packages/plugin-legacy/src/index.ts b/packages/plugin-legacy/src/index.ts index e22898032f854e..a2089ae52e3809 100644 --- a/packages/plugin-legacy/src/index.ts +++ b/packages/plugin-legacy/src/index.ts @@ -313,6 +313,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { fileName = fileName.replace('[name]', '[name]-legacy') } else { // entry.js -> entry-legacy.js + // eslint-disable-next-line regexp/no-super-linear-move -- fileName won't be so long fileName = fileName.replace(/(.+)\.(.+)/, '$1-legacy.$2') } @@ -453,7 +454,9 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { } const tags: HtmlTagDescriptor[] = [] - const htmlFilename = chunk.facadeModuleId?.replace(/\?.*$/, '') + const htmlFilename = chunk.facadeModuleId + ? trimQuery(chunk.facadeModuleId) + : undefined // 1. inject modern polyfills const modernPolyfillFilename = facadeToModernPolyfillMap.get( @@ -793,6 +796,11 @@ function wrapIIFEBabelPlugin(): BabelPlugin { } } +function trimQuery(id: string) { + const pos = id.lastIndexOf('?') + return pos < 0 ? id : id.slice(0, pos) +} + export const cspHashes = [ createHash('sha256').update(safari10NoModuleFix).digest('base64'), createHash('sha256').update(systemJSInlineCode).digest('base64'), diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index ad54bb909a593b..1b9ae222ead1f4 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -113,6 +113,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] { const importReactRE = /(?:^|\n)import\s+(?:\*\s+as\s+)?React(?:,|\s+)/ // Any extension, including compound ones like '.bs.js' + // eslint-disable-next-line regexp/no-super-linear-move -- id won't be so long const fileExtensionRE = /\.[^/\s?]+$/ const viteBabel: Plugin = { diff --git a/packages/plugin-vue/src/main.ts b/packages/plugin-vue/src/main.ts index 64ad9346d8c783..cb5d27ee7ce07e 100644 --- a/packages/plugin-vue/src/main.ts +++ b/packages/plugin-vue/src/main.ts @@ -473,7 +473,12 @@ async function linkSrcToDescriptor( (await pluginContext.resolve(src, descriptor.filename))?.id || src // #1812 if the src points to a dep file, the resolved id may contain a // version query. - setSrcDescriptor(srcFile.replace(/\?.*$/, ''), descriptor, scoped) + setSrcDescriptor(trimQuery(srcFile), descriptor, scoped) +} + +function trimQuery(id: string) { + const pos = id.lastIndexOf('?') + return pos < 0 ? id : id.slice(0, pos) } // these are built-in query parameters so should be ignored diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index 4f19efea33d295..00dea034103a33 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -593,7 +593,10 @@ export function injectQuery(url: string, queryToInject: string): string { } // can't use pathname from URL since it may be relative like ../ - const pathname = url.replace(/#.*$/, '').replace(/\?.*$/, '') + const pathname = trimEndFromLastOfThatChar( + trimEndFromLastOfThatChar(url, '#'), + '?' + ) const { search, hash } = new URL(url, 'http://vitejs.dev') return `${pathname}?${queryToInject}${search ? `&` + search.slice(1) : ''}${ @@ -601,4 +604,9 @@ export function injectQuery(url: string, queryToInject: string): string { }` } +function trimEndFromLastOfThatChar(input: string, char: string) { + const pos = input.lastIndexOf(char) + return pos < 0 ? input : input.slice(0, pos) +} + export { ErrorOverlay } diff --git a/packages/vite/src/client/overlay.ts b/packages/vite/src/client/overlay.ts index 57171b7ec13c0b..2c15d3217a6edc 100644 --- a/packages/vite/src/client/overlay.ts +++ b/packages/vite/src/client/overlay.ts @@ -127,7 +127,9 @@ code { ` +// eslint-disable-next-line regexp/no-super-linear-move -- won't use to long strings const fileRE = /(?:[a-zA-Z]:\\|\/).*?:\d+:\d+/g +// eslint-disable-next-line regexp/no-super-linear-move -- won't use to long strings const codeframeRE = /^(?:>?\s+\d+\s+\|.*|\s+\|\s*\^.*)\r?\n/gm // Allow `ErrorOverlay` to extend `HTMLElement` even in environments where diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index 662f6050a470a0..46eece2fa9db6d 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -40,6 +40,7 @@ const htmlTypesRE = /\.(html|vue|svelte|astro|imba)$/ // since even missed imports can be caught at runtime, and false positives will // simply be ignored. export const importsRE = + // eslint-disable-next-line regexp/no-super-linear-move -- TODO: FIXME backtracking /(?]*type\s*=\s*(?:"importmap"|'importmap'|importmap)[^>]*>.*?<\/script>/is + /]*type\s*=\s*(?:"importmap"|'importmap'|importmap)[^>]*>.*?<\/script>/is const moduleScriptRE = - /[ \t]*]*type\s*=\s*(?:"module"|'module'|module)[^>]*>/i + /]*type\s*=\s*(?:"module"|'module'|module)[^>]*>/i export const isHTMLProxy = (id: string): boolean => htmlProxyRE.test(id) @@ -986,11 +987,10 @@ export async function applyHtmlTransforms( } const importRE = /\bimport\s*("[^"]*[^\\]"|'[^']*[^\\]');*/g -const commentRE = /\/\*[\s\S]*?\*\/|\/\/.*$/gm function isEntirelyImport(code: string) { // only consider "side-effect" imports, which match