Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1049,9 +1049,16 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
const { importedCss, importedAssets } = (
bundle[file] as OutputChunk
).viteMetadata!
importedCss.forEach((file) =>
chunk.viteMetadata!.importedCss.add(file),
)
// Preserve original import order: ensure CSS coming from imported
// pure CSS chunks appears before the parent's existing CSS.
if (importedCss.size > 0) {
const parentCss = chunk.viteMetadata!.importedCss
const ordered = new Set<string>([
...importedCss,
...parentCss,
])
chunk.viteMetadata!.importedCss = ordered
}
importedAssets.forEach((file) =>
chunk.viteMetadata!.importedAssets.add(file),
)
Expand Down
26 changes: 26 additions & 0 deletions playground/css-order-manual-chunks/__tests__/order.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { describe, expect, test } from 'vitest'
import { isBuild, page, readFile } from '~utils'

describe.runIf(isBuild)('build', () => {
test('css links respect import order with manualChunks', async () => {
const html = readFile('dist/index.html') as string
// expect lib.css link appears before entry css link (index.css)
const libHref = /href="(.*?)\/assets\/lib-([\w-]+)\.css"/g

Check warning on line 8 in playground/css-order-manual-chunks/__tests__/order.spec.ts

View workflow job for this annotation

GitHub Actions / Lint: node-24, ubuntu-latest

The 'g' flag is unnecessary because the regex is used only once in 'RegExp.prototype.exec'
const indexHref = /href="(.*?)\/assets\/index-([\w-]+)\.css"/g

Check warning on line 9 in playground/css-order-manual-chunks/__tests__/order.spec.ts

View workflow job for this annotation

GitHub Actions / Lint: node-24, ubuntu-latest

The 'g' flag is unnecessary because the regex is used only once in 'RegExp.prototype.exec'

const libMatch = libHref.exec(html)
const indexMatch = indexHref.exec(html)

expect(libMatch, 'lib.css link should exist').toBeTruthy()
expect(indexMatch, 'index.css link should exist').toBeTruthy()

expect(libMatch!.index).toBeLessThan(indexMatch!.index)
})
})

test('runtime style precedence matches import order', async () => {
// lib.css sets .box { color: green }, base.css sets .box { color: red }
// If lib.css is loaded before index.css, final color should be red
const color = await page.$eval('#app', (el) => getComputedStyle(el).color)
expect(color).toBe('rgb(255, 0, 0)')
})
3 changes: 3 additions & 0 deletions playground/css-order-manual-chunks/base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.box {
color: red;
}
12 changes: 12 additions & 0 deletions playground/css-order-manual-chunks/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CSS Order Manual Chunks</title>
</head>
<body>
<div id="app">css order manual chunks</div>
<script type="module" src="/main.js"></script>
</body>
</html>
3 changes: 3 additions & 0 deletions playground/css-order-manual-chunks/lib.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.box {
color: green;
}
5 changes: 5 additions & 0 deletions playground/css-order-manual-chunks/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// simulate third-party big css split via manualChunks
import './lib.css'
import './base.css'

document.getElementById('app').className = 'box'
13 changes: 13 additions & 0 deletions playground/css-order-manual-chunks/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { defineConfig } from 'vite'

export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.endsWith('/lib.css')) return 'lib'
},
},
},
},
})