11import fs from 'node:fs'
22import fsp from 'node:fs/promises'
33import path from 'node:path'
4+ import { createHash } from 'node:crypto'
45import { fileURLToPath , pathToFileURL } from 'node:url'
56import postcssrc from 'postcss-load-config'
67import type {
@@ -1133,7 +1134,9 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
11331134 )
11341135 for ( const cssAsset of cssAssets ) {
11351136 if ( typeof cssAsset . source === 'string' ) {
1136- cssAsset . source = cssAsset . source . replace ( viteHashUpdateMarkerRE , '' )
1137+ cssAsset . source = cssAsset . source
1138+ . replace ( viteHashUpdateMarkerRE , '' )
1139+ . replace ( viteConfigHashMarkerRE , '' )
11371140 }
11381141 }
11391142 } ,
@@ -1900,6 +1903,7 @@ function combineSourcemapsIfExists(
19001903
19011904const viteHashUpdateMarker = '/*$vite$:1*/'
19021905const viteHashUpdateMarkerRE = / \/ \* \$ v i t e \$ : \d + \* \/ /
1906+ const viteConfigHashMarkerRE = / \/ \* \$ v i t e - c o n f i g - h a s h \$ : [ 0 - 9 a - f ] + \* \/ /
19031907
19041908async function finalizeCss ( css : string , config : ResolvedConfig ) {
19051909 // hoist external @imports and @charset to the top of the CSS chunk per spec (#1845 and #6333)
@@ -1919,6 +1923,15 @@ async function finalizeCss(css: string, config: ResolvedConfig) {
19191923 // to avoid that happening, we inject an additional string so that a different hash is generated
19201924 // for the same CSS content
19211925 css += viteHashUpdateMarker
1926+ // Include renderBuiltUrl in the CSS content hash so that changing
1927+ // the function produces different asset filenames
1928+ if ( config . experimental ?. renderBuiltUrl ) {
1929+ const hash = createHash ( 'sha256' )
1930+ . update ( config . experimental . renderBuiltUrl . toString ( ) )
1931+ . digest ( 'hex' )
1932+ . substring ( 0 , 8 )
1933+ css += `/*$vite-config-hash$:${ hash } */`
1934+ }
19221935 return css
19231936}
19241937
0 commit comments