@@ -316,6 +316,8 @@ export function cssPlugin(config: ResolvedConfig): Plugin {
316
316
export function cssPostPlugin ( config : ResolvedConfig ) : Plugin {
317
317
// styles initialization in buildStart causes a styling loss in watch
318
318
const styles : Map < string , string > = new Map < string , string > ( )
319
+ // list of css emit tasks to guarantee the files are emitted in a deterministic order
320
+ let emitTasks : Promise < void > [ ] = [ ]
319
321
let pureCssChunks : Set < RenderedChunk >
320
322
321
323
// when there are multiple rollup outputs and extracting CSS, only emit once,
@@ -353,6 +355,7 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
353
355
pureCssChunks = new Set < RenderedChunk > ( )
354
356
outputToExtractedCSSMap = new Map < NormalizedOutputOptions , string > ( )
355
357
hasEmitted = false
358
+ emitTasks = [ ]
356
359
} ,
357
360
358
361
async transform ( css , id , options ) {
@@ -563,7 +566,22 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
563
566
const cssFileName = ensureFileExt ( cssAssetName , '.css' )
564
567
565
568
chunkCSS = resolveAssetUrlsInCss ( chunkCSS , cssAssetName )
566
- chunkCSS = await finalizeCss ( chunkCSS , true , config )
569
+
570
+ const previousTask = emitTasks [ emitTasks . length - 1 ]
571
+ // finalizeCss is async which makes `emitFile` non-deterministic, so
572
+ // we use a `.then` to wait for previous tasks before finishing this
573
+ const thisTask = finalizeCss ( chunkCSS , true , config ) . then ( ( css ) => {
574
+ chunkCSS = css
575
+ // make sure the previous task is also finished, this works recursively
576
+ return previousTask
577
+ } )
578
+
579
+ // push this task so the next task can wait for this one
580
+ emitTasks . push ( thisTask )
581
+ const emitTasksLength = emitTasks . length
582
+
583
+ // wait for this and previous tasks to finish
584
+ await thisTask
567
585
568
586
// emit corresponding css file
569
587
const referenceId = this . emitFile ( {
@@ -577,6 +595,11 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
577
595
. get ( config ) !
578
596
. set ( referenceId , { originalName, isEntry } )
579
597
chunk . viteMetadata ! . importedCss . add ( this . getFileName ( referenceId ) )
598
+
599
+ if ( emitTasksLength === emitTasks . length ) {
600
+ // this is the last task, clear `emitTasks` to free up memory
601
+ emitTasks = [ ]
602
+ }
580
603
} else if ( ! config . build . ssr ) {
581
604
// legacy build and inline css
582
605
0 commit comments