From 14a0e88eac0ab735714f5ad4543a61c15253aa0f Mon Sep 17 00:00:00 2001 From: sapphi-red Date: Sun, 13 Nov 2022 23:00:00 +0900 Subject: [PATCH] perf: importsRE quadratic moves --- packages/vite/src/node/__tests__/scan.spec.ts | 7 +++---- packages/vite/src/node/optimizer/scan.ts | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/vite/src/node/__tests__/scan.spec.ts b/packages/vite/src/node/__tests__/scan.spec.ts index 0f9475562365d5..713743abdf1ee4 100644 --- a/packages/vite/src/node/__tests__/scan.spec.ts +++ b/packages/vite/src/node/__tests__/scan.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'vitest' -import { commentRE, importsRE, scriptRE } from '../optimizer/scan' +import { commentRE, extractImportPaths, scriptRE } from '../optimizer/scan' import { multilineCommentsRE, singlelineCommentsRE } from '../utils' describe('optimizer-scan:script-test', () => { @@ -89,8 +89,7 @@ describe('optimizer-scan:script-test', () => { ] shouldMatchArray.forEach((str) => { - importsRE.lastIndex = 0 - expect(importsRE.exec(str)[1]).toEqual("'vue'") + expect(extractImportPaths(str)).toStrictEqual(["import 'vue'"]) }) const shouldFailArray = [ @@ -102,7 +101,7 @@ describe('optimizer-scan:script-test', () => { `import type Bar from 'foo'` ] shouldFailArray.forEach((str) => { - expect(importsRE.test(str)).toBe(false) + expect(extractImportPaths(str)).toStrictEqual([]) }) }) diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index 46eece2fa9db6d..42411ded8cf3e5 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -39,9 +39,10 @@ const htmlTypesRE = /\.(html|vue|svelte|astro|imba)$/ // use Acorn because it's slow. Luckily this doesn't have to be bullet proof // 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 - /(? @@ -325,7 +326,9 @@ function esbuildScanPlugin( // since they may be used in the template const contents = content + - (loader.startsWith('ts') ? extractImportPaths(content) : '') + (loader.startsWith('ts') + ? extractImportPaths(content).join('\n') + : '') const key = `${path}?id=${scriptId++}` if (contents.includes('import.meta.glob')) { @@ -524,22 +527,22 @@ function esbuildScanPlugin( * the solution is to add `import 'x'` for every source to force * esbuild to keep crawling due to potential side effects. */ -function extractImportPaths(code: string) { +export function extractImportPaths(code: string): string[] { // empty singleline & multiline comments to avoid matching comments code = code .replace(multilineCommentsRE, '/* */') .replace(singlelineCommentsRE, '') - let js = '' + const imports = [] let m while ((m = importsRE.exec(code)) != null) { // This is necessary to avoid infinite loops with zero-width matches if (m.index === importsRE.lastIndex) { importsRE.lastIndex++ } - js += `\nimport ${m[1]}` + imports.push(`import ${m[1]}`) } - return js + return imports } function shouldExternalizeDep(resolvedId: string, rawId: string): boolean {