Skip to content

Commit d2f1381

Browse files
authoredJan 25, 2023
fix(css): insert styles in the same position (#11763)
1 parent 568bdab commit d2f1381

File tree

8 files changed

+43
-1
lines changed

8 files changed

+43
-1
lines changed
 

‎packages/vite/src/client/client.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ const sheetsMap = new Map<
347347
string,
348348
HTMLStyleElement | CSSStyleSheet | undefined
349349
>()
350+
// all css imports should be inserted at the same position
351+
// because after build it will be a single css file
352+
let lastInsertedStyle: HTMLStyleElement | undefined
350353

351354
export function updateStyle(id: string, content: string): void {
352355
let style = sheetsMap.get(id)
@@ -374,7 +377,19 @@ export function updateStyle(id: string, content: string): void {
374377
style.setAttribute('type', 'text/css')
375378
style.setAttribute('data-vite-dev-id', id)
376379
style.textContent = content
377-
document.head.appendChild(style)
380+
381+
if (!lastInsertedStyle) {
382+
document.head.appendChild(style)
383+
384+
// reset lastInsertedStyle after async
385+
// because dynamically imported css will be splitted into a different file
386+
setTimeout(() => {
387+
lastInsertedStyle = undefined
388+
}, 0)
389+
} else {
390+
lastInsertedStyle.insertAdjacentElement('afterend', style)
391+
}
392+
lastInsertedStyle = style
378393
} else {
379394
style.textContent = content
380395
}

‎playground/css-codesplit/__tests__/css-codesplit.spec.ts

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ test('should load dynamic import with module', async () => {
2121
expect(await getColor('.mod')).toBe('yellow')
2222
})
2323

24+
test('style order should be consistent when style tag is inserted by JS', async () => {
25+
expect(await getColor('.order-bulk')).toBe('orange')
26+
await page.click('.order-bulk-update')
27+
expect(await getColor('.order-bulk')).toBe('green')
28+
})
29+
2430
describe.runIf(isBuild)('build', () => {
2531
test('should remove empty chunk', async () => {
2632
expect(findAssetFile(/style.*\.js$/)).toBe('')

‎playground/css-codesplit/index.html

+5
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,10 @@ <h2>This should be blue</h2>
77
<p class="mod">This should be yellow</p>
88
<p class="dynamic-module"></p>
99

10+
<p class="order-bulk">
11+
This should be orange
12+
<button class="order-bulk-update">change to green</button>
13+
</p>
14+
1015
<script type="module" src="/main.js"></script>
1116
<div id="app"></div>

‎playground/css-codesplit/main.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import './style.css'
22
import './main.css'
3+
import './order'
34

45
import('./async.css')
56

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.order-bulk {
2+
color: blue;
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.order-bulk {
2+
color: green;
3+
}
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import './insert' // inserts "color: orange"
2+
import './base.css' // includes "color: blue"
3+
4+
document.querySelector('.order-bulk-update').addEventListener('click', () => {
5+
import('./dynamic.css') // includes "color: green"
6+
})
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const style = document.createElement('style')
2+
style.textContent = '.order-bulk { color: orange; }'
3+
document.head.appendChild(style)

0 commit comments

Comments
 (0)
Please sign in to comment.