diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 09cc44803d8c90..94d7f48e2c6180 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -1074,6 +1074,8 @@ export async function preprocessCSS( return await compileCSS(filename, code, config) } +const postcssReturnsVirtualFilesRE = /^<.+>$/ + export async function formatPostcssSourceMap( rawMap: ExistingRawSourceMap, file: string, @@ -1083,8 +1085,7 @@ export async function formatPostcssSourceMap( const sources = rawMap.sources.map((source) => { const cleanSource = cleanUrl(decodeURIComponent(source)) - // postcss returns virtual files - if (/^<.+>$/.test(cleanSource)) { + if (postcssReturnsVirtualFilesRE.test(cleanSource)) { return `\0${cleanSource}` } diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index f730fc9e093bbf..7933618d49da08 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -19,6 +19,7 @@ import { toAbsoluteGlob } from './importMetaGlob' export const dynamicImportHelperId = '\0vite/dynamic-import-helper' +const relativePathRE = /^\.{1,2}\// interface DynamicImportRequest { as?: keyof KnownAsTypeMap } @@ -122,7 +123,7 @@ export async function transformDynamicImport( await toAbsoluteGlob(rawPattern, root, importer, resolve), ) - if (!/^\.{1,2}\//.test(newRawPattern)) { + if (!relativePathRE.test(newRawPattern)) { newRawPattern = `./${newRawPattern}` } diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index 55b079577ce679..f12b6cba1b97c0 100644 --- a/packages/vite/src/node/plugins/esbuild.ts +++ b/packages/vite/src/node/plugins/esbuild.ts @@ -30,6 +30,9 @@ const INJECT_HELPERS_IIFE_RE = const INJECT_HELPERS_UMD_RE = /^(.*?)(\(function\([^)]*\)\s*\{.+?amd.+?function\([^)]*\)\s*\{.*?"use strict";)/s +const validExtensionRE = /\.\w+$/ +const jsxExtensionsRE = /\.(?:j|t)sx\b/ + let server: ViteDevServer export interface ESBuildOptions extends TransformOptions { @@ -75,7 +78,7 @@ export async function transformWithEsbuild( // if the id ends with a valid ext, use it (e.g. vue blocks) // otherwise, cleanup the query before checking the ext const ext = path - .extname(/\.\w+$/.test(filename) ? filename : cleanUrl(filename)) + .extname(validExtensionRE.test(filename) ? filename : cleanUrl(filename)) .slice(1) if (ext === 'cjs' || ext === 'mjs') { @@ -247,7 +250,7 @@ export function esbuildPlugin(options: ESBuildOptions): Plugin { this.warn(prettifyMessage(m, code)) }) } - if (jsxInject && /\.(?:j|t)sx\b/.test(id)) { + if (jsxInject && jsxExtensionsRE.test(id)) { result.code = jsxInject + ';' + result.code } return { diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index b18c9c6bc2f511..ec377083a2d688 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -78,6 +78,13 @@ export const canSkipImportAnalysis = (id: string): boolean => const optimizedDepChunkRE = /\/chunk-[A-Z\d]{8}\.js/ const optimizedDepDynamicRE = /-[A-Z\d]{8}\.js/ +const hasImportInQueryParamsRE = /[?&]import=?\b/ + +const hasViteIgnoreRE = /\/\*\s*@vite-ignore\s*\*\// + +const cleanUpRawUrlRE = /\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm +const urlIsStringRE = /^(?:'.*'|".*"|`.*`)$/ + export function isExplicitImportRequired(url: string): boolean { return !isJSRequest(cleanUrl(url)) && !isCSSRequest(url) } @@ -373,7 +380,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { // query can break 3rd party plugin's extension checks. if ( (isRelative || isSelfImport) && - !/[?&]import=?\b/.test(url) && + !hasImportInQueryParamsRE.test(url) && !url.match(DEP_VERSION_RE) ) { const versionMatch = importer.match(DEP_VERSION_RE) @@ -613,7 +620,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { } else if (!importer.startsWith(clientDir)) { if (!importer.includes('node_modules')) { // check @vite-ignore which suppresses dynamic import warning - const hasViteIgnore = /\/\*\s*@vite-ignore\s*\*\//.test( + const hasViteIgnore = hasViteIgnoreRE.test( // complete expression inside parens source.slice(dynamicIndex + 1, end), ) @@ -637,11 +644,9 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { } if (!ssr) { - const url = rawUrl - .replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '') - .trim() + const url = rawUrl.replace(cleanUpRawUrlRE, '').trim() if ( - !/^(?:'.*'|".*"|`.*`)$/.test(url) || + !urlIsStringRE.test(url) || isExplicitImportRequired(url.slice(1, -1)) ) { needQueryInjectHelper = true diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 9404fdde034ed7..2ba737063df691 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -62,6 +62,8 @@ export const optionalPeerDepId = '__vite-optional-peer-dep' const nodeModulesInPathRE = /(?:^|\/)node_modules\// const subpathImportsPrefix = '#' +const startsWithWordCharRE = /^\w/ + const isDebug = process.env.DEBUG const debug = createDebugger('vite:resolve-details', { onlyWhenFocused: true, @@ -279,7 +281,8 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { // relative if ( id.startsWith('.') || - ((preferRelative || importer?.endsWith('.html')) && /^\w/.test(id)) + ((preferRelative || importer?.endsWith('.html')) && + startsWithWordCharRE.test(id)) ) { const basedir = importer ? path.dirname(importer) : process.cwd() const fsPath = path.resolve(basedir, id)