From a79273929e5b2d6a483b7268255b1ce3e8e50b4e Mon Sep 17 00:00:00 2001 From: thy486 Date: Mon, 6 Jan 2025 17:40:27 +0800 Subject: [PATCH 1/2] fix(html): fix css disorder when building multiple entry html --- packages/vite/src/node/plugins/html.ts | 61 +++++++++++++++++++------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index cb9bf87192258d..26b7aab5a58f2e 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 analyzedChunk = new Map>() const inlineEntryChunk = new Set() const getImportedChunks = ( chunk: OutputChunk, @@ -781,32 +781,61 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { chunk: OutputChunk, toOutputPath: (filename: string) => string, seen: Set = new Set(), + parentImports?: Set, + circle: Set = new Set(), ): HtmlTagDescriptor[] => { const tags: HtmlTagDescriptor[] = [] + if (circle.has(chunk)) { + return tags + } + circle.add(chunk) + let analyzedChunkImportCss: Set + const processImportedCss = (files: Set): void => { + files.forEach((file) => { + if (parentImports) { + parentImports.add(file) + } + if (!seen.has(file)) { + seen.add(file) + tags.push({ + tag: 'link', + attrs: { + rel: 'stylesheet', + crossorigin: true, + href: toOutputPath(file), + }, + }) + } + }) + } if (!analyzedChunk.has(chunk)) { - analyzedChunk.set(chunk, 1) + analyzedChunkImportCss = new Set() chunk.imports.forEach((file) => { const importee = bundle[file] if (importee?.type === 'chunk') { - tags.push(...getCssTagsForChunk(importee, toOutputPath, seen)) + tags.push( + ...getCssTagsForChunk( + importee, + toOutputPath, + seen, + analyzedChunkImportCss, + circle, + ), + ) } }) - } - - chunk.viteMetadata!.importedCss.forEach((file) => { - if (!seen.has(file)) { - seen.add(file) - tags.push({ - tag: 'link', - attrs: { - rel: 'stylesheet', - crossorigin: true, - href: toOutputPath(file), - }, + analyzedChunk.set(chunk, analyzedChunkImportCss) + if (parentImports) { + analyzedChunkImportCss.forEach((file) => { + parentImports.add(file) }) } - }) + } else { + analyzedChunkImportCss = analyzedChunk.get(chunk)! + processImportedCss(analyzedChunkImportCss) + } + processImportedCss(chunk.viteMetadata!.importedCss) return tags } From cf9cfc0428b36fe7f43769d6050994f174c3d29e Mon Sep 17 00:00:00 2001 From: thy486 Date: Fri, 10 Jan 2025 10:59:59 +0800 Subject: [PATCH 2/2] style(html): follow the review suggestions to improve the readability of the code for extracting css tags --- packages/vite/src/node/plugins/html.ts | 106 ++++++++++++------------- 1 file changed, 50 insertions(+), 56 deletions(-) diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index 26b7aab5a58f2e..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,68 +777,62 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { }, }) - const getCssTagsForChunk = ( - chunk: OutputChunk, + const toStyleSheetLinkTag = ( + file: string, toOutputPath: (filename: string) => string, - seen: Set = new Set(), - parentImports?: Set, - circle: Set = new Set(), - ): HtmlTagDescriptor[] => { - const tags: HtmlTagDescriptor[] = [] - if (circle.has(chunk)) { - return tags + ): 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 [] } - circle.add(chunk) - let analyzedChunkImportCss: Set - const processImportedCss = (files: Set): void => { - files.forEach((file) => { - if (parentImports) { - parentImports.add(file) - } - if (!seen.has(file)) { - seen.add(file) - tags.push({ - tag: 'link', - attrs: { - rel: 'stylesheet', - crossorigin: true, - href: toOutputPath(file), - }, - }) - } - }) + 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 } - if (!analyzedChunk.has(chunk)) { - analyzedChunkImportCss = new Set() - chunk.imports.forEach((file) => { - const importee = bundle[file] - if (importee?.type === 'chunk') { - tags.push( - ...getCssTagsForChunk( - importee, - toOutputPath, - seen, - analyzedChunkImportCss, - circle, - ), - ) - } - }) - analyzedChunk.set(chunk, analyzedChunkImportCss) - if (parentImports) { - analyzedChunkImportCss.forEach((file) => { - parentImports.add(file) - }) + + const files: string[] = [] + chunk.imports.forEach((file) => { + const importee = bundle[file] + if (importee?.type === 'chunk') { + files.push(...getCssFilesForChunk(importee, seenChunks, seenCss)) } - } else { - analyzedChunkImportCss = analyzedChunk.get(chunk)! - processImportedCss(analyzedChunkImportCss) - } + }) + analyzedImportedCssFiles.set(chunk, files) - processImportedCss(chunk.viteMetadata!.importedCss) - return tags + chunk.viteMetadata!.importedCss.forEach((file) => { + if (!seenCss.has(file)) { + seenCss.add(file) + files.push(file) + } + }) + + 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),