diff --git a/packages/vite/src/node/plugins/asset.ts b/packages/vite/src/node/plugins/asset.ts index 74f0220a4e9c19..5954e1cd92fa2e 100644 --- a/packages/vite/src/node/plugins/asset.ts +++ b/packages/vite/src/node/plugins/asset.ts @@ -46,7 +46,7 @@ export const inlineRE = /[?&]inline\b/ const assetCache = new WeakMap>() /** a set of referenceId for entry CSS assets for each environment */ -export const cssEntriesMap = new WeakMap>() +export const cssEntriesMap = new WeakMap>() // add own dictionary entry by directly assigning mrmime export function registerCustomMime(): void { @@ -148,7 +148,7 @@ export function assetPlugin(config: ResolvedConfig): Plugin { buildStart() { assetCache.set(this.environment, new Map()) - cssEntriesMap.set(this.environment, new Set()) + cssEntriesMap.set(this.environment, new Map()) }, resolveId: { diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index daac55989b4429..fff6ae63d9731a 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -863,7 +863,7 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { source: chunkCSS, }) if (isEntry) { - cssEntriesMap.get(this.environment)!.add(referenceId) + cssEntriesMap.get(this.environment)!.set(chunk.name, referenceId) } chunk.viteMetadata!.importedCss.add(this.getFileName(referenceId)) } else if (this.environment.config.consumer === 'client') { diff --git a/packages/vite/src/node/plugins/manifest.ts b/packages/vite/src/node/plugins/manifest.ts index 064e20d2142818..1b94bd7f28e619 100644 --- a/packages/vite/src/node/plugins/manifest.ts +++ b/packages/vite/src/node/plugins/manifest.ts @@ -21,7 +21,7 @@ export interface ManifestChunk { assets?: string[] isEntry?: boolean name?: string - names?: string[] + // names field is deprecated (removed from types, but still emitted for backward compatibility) isDynamicEntry?: boolean imports?: string[] dynamicImports?: string[] @@ -122,25 +122,27 @@ export function manifestPlugin(): Plugin { function createAsset( asset: OutputAsset, src: string, - isEntry?: boolean, + name?: string, ): ManifestChunk { const manifestChunk: ManifestChunk = { file: asset.fileName, src, } - if (isEntry) { + if (name) { manifestChunk.isEntry = true + manifestChunk.name = name + // @ts-expect-error keep names field for backward compatibility manifestChunk.names = asset.names } return manifestChunk } const entryCssReferenceIds = cssEntriesMap.get(this.environment)! - const entryCssAssetFileNames = new Set() - for (const id of entryCssReferenceIds) { + const entryCssAssetFileNames = new Map() + for (const [name, id] of entryCssReferenceIds) { try { const fileName = this.getFileName(id) - entryCssAssetFileNames.add(fileName) + entryCssAssetFileNames.set(fileName, name) } catch { // The asset was generated as part of a different output option. // It was already handled during the previous run of this plugin. @@ -157,8 +159,8 @@ export function manifestPlugin(): Plugin { chunk.originalFileNames.length > 0 ? chunk.originalFileNames[0] : `_${path.basename(chunk.fileName)}` - const isEntry = entryCssAssetFileNames.has(chunk.fileName) - const asset = createAsset(chunk, src, isEntry) + const name = entryCssAssetFileNames.get(chunk.fileName) + const asset = createAsset(chunk, src, name) // If JS chunk and asset chunk are both generated from the same source file, // prioritize JS chunk as it contains more information diff --git a/playground/backend-integration/__tests__/backend-integration.spec.ts b/playground/backend-integration/__tests__/backend-integration.spec.ts index 5a314d6b9d5a76..e0aeef00d1a793 100644 --- a/playground/backend-integration/__tests__/backend-integration.spec.ts +++ b/playground/backend-integration/__tests__/backend-integration.spec.ts @@ -54,6 +54,7 @@ describe.runIf(isBuild)('build', () => { const scssAssetEntry = manifest['nested/blue.scss'] const imgAssetEntry = manifest['../images/logo.png'] const dirFooAssetEntry = manifest['../../dir/foo.css'] + const customNameAssetEntry = manifest['../../dir/custom.css'] const iconEntrypointEntry = manifest['icon.png'] const waterContainerEntry = manifest['water-container.svg'] expect(htmlEntry.css.length).toEqual(1) @@ -74,7 +75,8 @@ describe.runIf(isBuild)('build', () => { expect(dirFooAssetEntry).not.toBeUndefined() // '\\' should not be used even on windows // use the entry name expect(dirFooAssetEntry.file).toMatch('assets/bar-') - expect(dirFooAssetEntry.names).toStrictEqual(['bar.css']) + expect(dirFooAssetEntry.name).toStrictEqual('bar.css') + expect(customNameAssetEntry.name).toStrictEqual('bar.custom') expect(iconEntrypointEntry?.file).not.toBeUndefined() expect(waterContainerEntry?.file).not.toBeUndefined() }) diff --git a/playground/backend-integration/dir/custom.css b/playground/backend-integration/dir/custom.css new file mode 100644 index 00000000000000..086058a71f67e2 --- /dev/null +++ b/playground/backend-integration/dir/custom.css @@ -0,0 +1,3 @@ +.custom { + color: red; +} diff --git a/playground/backend-integration/vite.config.js b/playground/backend-integration/vite.config.js index f432f139a4f6d9..7560c31541ac22 100644 --- a/playground/backend-integration/vite.config.js +++ b/playground/backend-integration/vite.config.js @@ -23,6 +23,10 @@ function BackendIntegrationExample() { entrypoints.push(['tailwindcss-colors', 'tailwindcss/colors.js']) entrypoints.push(['bar.css', path.resolve(__dirname, './dir/foo.css')]) + entrypoints.push([ + 'bar.custom', + path.resolve(__dirname, './dir/custom.css'), + ]) return { server: {