diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index 0c3163adfb1c06..a8801e616a59d1 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -365,9 +365,11 @@ const sheetsMap = new Map() // collect existing style elements that may have been inserted during SSR // to avoid FOUC or duplicate styles -document.querySelectorAll('style[data-vite-dev-id]').forEach((el) => { - sheetsMap.set(el.getAttribute('data-vite-dev-id')!, el as HTMLStyleElement) -}) +if ('document' in globalThis) { + document.querySelectorAll('style[data-vite-dev-id]').forEach((el) => { + sheetsMap.set(el.getAttribute('data-vite-dev-id')!, el as HTMLStyleElement) + }) +} // all css imports should be inserted at the same position // because after build it will be a single css file @@ -591,22 +593,4 @@ export function createHotContext(ownerPath: string): ViteHotContext { return hot } -/** - * urls here are dynamic import() urls that couldn't be statically analyzed - */ -export function injectQuery(url: string, queryToInject: string): string { - // skip urls that won't be handled by vite - if (url[0] !== '.' && url[0] !== '/') { - return url - } - - // can't use pathname from URL since it may be relative like ../ - const pathname = url.replace(/#.*$/, '').replace(/\?.*$/, '') - const { search, hash } = new URL(url, 'http://vitejs.dev') - - return `${pathname}?${queryToInject}${search ? `&` + search.slice(1) : ''}${ - hash || '' - }` -} - export { ErrorOverlay } diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 119f0192cabb43..98fcc1e6a4bdc2 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -80,6 +80,28 @@ const hasViteIgnoreRE = /\/\*\s*@vite-ignore\s*\*\// const cleanUpRawUrlRE = /\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm const urlIsStringRE = /^(?:'.*'|".*"|`.*`)$/ +const importAnalysisHelperId = '\0vite/import-analysis-helper' +const wrapppedImportAnalysisHelperId = wrapId(importAnalysisHelperId) + +/** + * urls here are dynamic import() urls that couldn't be statically analyzed. + * browser-safe version of `injectQuery` util. + */ +function __vite__injectQuery(url: string, queryToInject: string): string { + // skip urls that won't be handled by vite + if (url[0] !== '.' && url[0] !== '/') { + return url + } + + // can't use pathname from URL since it may be relative like ../ + const pathname = url.replace(/#.*$/, '').replace(/\?.*$/, '') + const { search, hash } = new URL(url, 'http://vitejs.dev') + + return `${pathname}?${queryToInject}${search ? `&` + search.slice(1) : ''}${ + hash || '' + }` +} + interface UrlPosition { url: string start: number @@ -201,6 +223,18 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { server = _server }, + resolveId(id) { + if (id === importAnalysisHelperId) { + return id + } + }, + + load(id) { + if (id === importAnalysisHelperId) { + return 'export ' + __vite__injectQuery.toString() + } + }, + async transform(source, importer, options) { // In a real app `server` is always defined, but it is undefined when // running src/node/server/__tests__/pluginContainer.spec.ts @@ -734,7 +768,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { if (needQueryInjectHelper) { str().prepend( - `import { injectQuery as __vite__injectQuery } from "${clientPublicPath}";`, + `import { __vite__injectQuery } from "${wrapppedImportAnalysisHelperId}";`, ) }