From 89fdc0015e1d74275d21dbcb4119200760e4a0e8 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Fri, 12 Jul 2024 01:04:21 +0200 Subject: [PATCH] perf(CSSEntryPointsPlugin): Only visit chunks once per entry point Signed-off-by: Ferdinand Thiessen --- lib/plugins/CSSEntryPoints.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/plugins/CSSEntryPoints.ts b/lib/plugins/CSSEntryPoints.ts index d3a2c9e..d8f4e94 100644 --- a/lib/plugins/CSSEntryPoints.ts +++ b/lib/plugins/CSSEntryPoints.ts @@ -64,7 +64,7 @@ export function CSSEntryPointsPlugin(options?: CSSEntryPointsPluginOptions) { }, generateBundle(options, bundle) { - for (const chunk of Object.values(bundle)) { + for (const [chunkName, chunk] of Object.entries(bundle)) { // Only handle entry points if (chunk.type !== 'chunk' || !chunk.isEntry) { continue @@ -72,8 +72,15 @@ export function CSSEntryPointsPlugin(options?: CSSEntryPointsPluginOptions) { // Set of all synchronously imported CSS of this entry point const importedCSS = new Set(chunk.viteMetadata?.importedCss ?? []) + const visitedChunks = new Set() const getImportedCSS = (importedNames: string[]) => { for (const importedName of importedNames) { + // skip if already extracted + if (visitedChunks.has(importedName)) { + continue + } + visitedChunks.add(importedName) + const importedChunk = bundle[importedName] // Skip non chunks if (importedChunk.type !== 'chunk') { @@ -86,7 +93,7 @@ export function CSSEntryPointsPlugin(options?: CSSEntryPointsPluginOptions) { .forEach((name: string) => importedCSS.add(name)) } } - getImportedCSS(chunk.imports) + getImportedCSS([chunkName]) // Skip empty entries if not configured to output empty CSS if (importedCSS.size === 0 && !pluginOptions.createEmptyEntryPoints) { @@ -102,7 +109,11 @@ export function CSSEntryPointsPlugin(options?: CSSEntryPointsPluginOptions) { const cssName = `${entryName}.css` // Keep original path - const path = dirname(typeof options.assetFileNames === 'string' ? options.assetFileNames : options.assetFileNames({ type: 'asset', source: '', name: 'name.css' })) + const path = dirname( + typeof options.assetFileNames === 'string' + ? options.assetFileNames + : options.assetFileNames({ type: 'asset', source: '', name: 'name.css' }) + ) this.emitFile({ type: 'asset',