Describe the bug
My main entry point starts with
import "virtual:uno.css"
import "./Components/Css/index.css";
// Then JS imports, some of which have associated CSS because of <style> tag in Vue SFC.
But when bundling for production, the index.css chunk, containing unocss output and the index.css imported above, comes last.
This can be observed with cssCodeSplit: true because that index.css is last included in html, or with cssCodeSplit: false because its content is last in the merged css bundle.
I have debugged the issue when cssCodeSplit: false and will explain below what happens.
Reproduction
https://stackblitz.com/edit/vitejs-vite-1tvfcfrw?file=src%2Fmain.js
Steps to reproduce
Idea in repro above is that main.js imports style.css first, then indirectly counter.js imports counter-style.css next.
Counter-style overrides the .counter color to red, which is what happens in dev mode, live in vite.new.
I don't know how to test a production bundle on vite.new, but I expect the order of scripts to be reversed (and the counter to be black).
I explain why below.
System Info
System:
OS: Windows 11 10.0.26100
CPU: (20) x64 13th Gen Intel(R) Core(TM) i7-1370P
Memory: 11.85 GB / 31.64 GB
Binaries:
Node: 25.9.0 - C:\Users\***\scoop\apps\nodejs\current\node.EXE
npm: 11.12.1 - C:\Users\***\scoop\apps\nodejs\current\npm.CMD
Browsers:
Edge: Chromium (143.0.3650.75)
Internet Explorer: 11.0.26100.7309
Not sure why that command doesn't list Vite version, anyway:
Vite: 8.0.9
Used Package Manager
npm
Logs
I have debugged the issue, when cssCodeSplit: false.
The culprit is the collect function here, which attempts to preserve order:
https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/css.ts#L1010-L1022
It tries to include in order: the static imports, then the dynamic imports, then the module own styles.
The key issue is that when a JS module does import "style.css", this isn't listed in chunk.imports.
Instead, the CSS ends up attached to current chunk in chunkCSSMap, which is added last.
In my own project, moving the line
extractedCss += chunkCSSMap.get(chunk.preliminaryFileName) ?? ''
first solves the issue, but I don't think it's the right fix, for two reasons:
- It doesn't solve the ordering issue amongst static import. What if
import "virtual:uno.css" wasn't the first import in my file and we had JS with an indirect CSS import first?
- It's probably incorrect for chunks representing Vue components with
<style> tags, those ones should come after static imports.
I believe the right fix is for Vite to create one empty chunk for each import "xyz.css", that is listed in chunk.imports in correct order, and attach the chunkCSSMap to this chunk instead.
Everything should then be in right order.
Validations
Describe the bug
My main entry point starts with
But when bundling for production, the
index.csschunk, containing unocss output and theindex.cssimported above, comes last.This can be observed with
cssCodeSplit: truebecause thatindex.cssis last included in html, or withcssCodeSplit: falsebecause its content is last in the merged css bundle.I have debugged the issue when
cssCodeSplit: falseand will explain below what happens.Reproduction
https://stackblitz.com/edit/vitejs-vite-1tvfcfrw?file=src%2Fmain.js
Steps to reproduce
Idea in repro above is that main.js imports style.css first, then indirectly counter.js imports counter-style.css next.
Counter-style overrides the .counter color to red, which is what happens in dev mode, live in vite.new.
I don't know how to test a production bundle on vite.new, but I expect the order of scripts to be reversed (and the counter to be black).
I explain why below.
System Info
System: OS: Windows 11 10.0.26100 CPU: (20) x64 13th Gen Intel(R) Core(TM) i7-1370P Memory: 11.85 GB / 31.64 GB Binaries: Node: 25.9.0 - C:\Users\***\scoop\apps\nodejs\current\node.EXE npm: 11.12.1 - C:\Users\***\scoop\apps\nodejs\current\npm.CMD Browsers: Edge: Chromium (143.0.3650.75) Internet Explorer: 11.0.26100.7309 Not sure why that command doesn't list Vite version, anyway: Vite: 8.0.9Used Package Manager
npm
Logs
I have debugged the issue, when
cssCodeSplit: false.The culprit is the
collectfunction here, which attempts to preserve order:https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/css.ts#L1010-L1022
It tries to include in order: the static imports, then the dynamic imports, then the module own styles.
The key issue is that when a JS module does
import "style.css", this isn't listed inchunk.imports.Instead, the CSS ends up attached to current chunk in
chunkCSSMap, which is added last.In my own project, moving the line
extractedCss += chunkCSSMap.get(chunk.preliminaryFileName) ?? ''first solves the issue, but I don't think it's the right fix, for two reasons:
import "virtual:uno.css"wasn't the first import in my file and we had JS with an indirect CSS import first?<style>tags, those ones should come after static imports.I believe the right fix is for Vite to create one empty chunk for each
import "xyz.css", that is listed inchunk.importsin correct order, and attach thechunkCSSMapto this chunk instead.Everything should then be in right order.
Validations