diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index cb9bf87192258d..537f58470a9cbd 100644 --- a/packages/vite/src/node/plugins/html.ts +++ b/packages/vite/src/node/plugins/html.ts @@ -717,7 +717,7 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { }, async generateBundle(options, bundle) { - const analyzedChunk = new Map() + const analyzedImportedCssFiles = new Map() const inlineEntryChunk = new Set() const getImportedChunks = ( chunk: OutputChunk, @@ -777,39 +777,62 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { }, }) - const getCssTagsForChunk = ( - chunk: OutputChunk, + const toStyleSheetLinkTag = ( + file: string, toOutputPath: (filename: string) => string, - seen: Set = new Set(), - ): HtmlTagDescriptor[] => { - const tags: HtmlTagDescriptor[] = [] - if (!analyzedChunk.has(chunk)) { - analyzedChunk.set(chunk, 1) - chunk.imports.forEach((file) => { - const importee = bundle[file] - if (importee?.type === 'chunk') { - tags.push(...getCssTagsForChunk(importee, toOutputPath, seen)) - } - }) + ): HtmlTagDescriptor => ({ + tag: 'link', + attrs: { + rel: 'stylesheet', + crossorigin: true, + href: toOutputPath(file), + }, + }) + + const getCssFilesForChunk = ( + chunk: OutputChunk, + seenChunks: Set = new Set(), + seenCss: Set = new Set(), + ): string[] => { + if (seenChunks.has(chunk.fileName)) { + return [] + } + seenChunks.add(chunk.fileName) + + if (analyzedImportedCssFiles.has(chunk)) { + const files = analyzedImportedCssFiles.get(chunk)! + const additionals = files.filter((file) => !seenCss.has(file)) + additionals.forEach((file) => seenCss.add(file)) + return additionals } + const files: string[] = [] + chunk.imports.forEach((file) => { + const importee = bundle[file] + if (importee?.type === 'chunk') { + files.push(...getCssFilesForChunk(importee, seenChunks, seenCss)) + } + }) + analyzedImportedCssFiles.set(chunk, files) + chunk.viteMetadata!.importedCss.forEach((file) => { - if (!seen.has(file)) { - seen.add(file) - tags.push({ - tag: 'link', - attrs: { - rel: 'stylesheet', - crossorigin: true, - href: toOutputPath(file), - }, - }) + if (!seenCss.has(file)) { + seenCss.add(file) + files.push(file) } }) - return tags + return files } + const getCssTagsForChunk = ( + chunk: OutputChunk, + toOutputPath: (filename: string) => string, + ) => + getCssFilesForChunk(chunk).map((file) => + toStyleSheetLinkTag(file, toOutputPath), + ) + for (const [normalizedId, html] of processedHtml(this)) { const relativeUrlPath = normalizePath( path.relative(config.root, normalizedId),