Skip to content

Commit

Permalink
fix(css): insert styles in the same position (vitejs#11763)
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red authored and futurGH committed Feb 26, 2023
1 parent 3c50985 commit 4682524
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 1 deletion.
17 changes: 16 additions & 1 deletion packages/vite/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,9 @@ const sheetsMap = new Map<
string,
HTMLStyleElement | CSSStyleSheet | undefined
>()
// all css imports should be inserted at the same position
// because after build it will be a single css file
let lastInsertedStyle: HTMLStyleElement | undefined

export function updateStyle(id: string, content: string): void {
let style = sheetsMap.get(id)
Expand Down Expand Up @@ -374,7 +377,19 @@ export function updateStyle(id: string, content: string): void {
style.setAttribute('type', 'text/css')
style.setAttribute('data-vite-dev-id', id)
style.textContent = content
document.head.appendChild(style)

if (!lastInsertedStyle) {
document.head.appendChild(style)

// reset lastInsertedStyle after async
// because dynamically imported css will be splitted into a different file
setTimeout(() => {
lastInsertedStyle = undefined
}, 0)
} else {
lastInsertedStyle.insertAdjacentElement('afterend', style)
}
lastInsertedStyle = style
} else {
style.textContent = content
}
Expand Down
6 changes: 6 additions & 0 deletions playground/css-codesplit/__tests__/css-codesplit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ test('should load dynamic import with module', async () => {
expect(await getColor('.mod')).toBe('yellow')
})

test('style order should be consistent when style tag is inserted by JS', async () => {
expect(await getColor('.order-bulk')).toBe('orange')
await page.click('.order-bulk-update')
expect(await getColor('.order-bulk')).toBe('green')
})

describe.runIf(isBuild)('build', () => {
test('should remove empty chunk', async () => {
expect(findAssetFile(/style.*\.js$/)).toBe('')
Expand Down
5 changes: 5 additions & 0 deletions playground/css-codesplit/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,10 @@ <h2>This should be blue</h2>
<p class="mod">This should be yellow</p>
<p class="dynamic-module"></p>

<p class="order-bulk">
This should be orange
<button class="order-bulk-update">change to green</button>
</p>

<script type="module" src="/main.js"></script>
<div id="app"></div>
1 change: 1 addition & 0 deletions playground/css-codesplit/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import './style.css'
import './main.css'
import './order'

import('./async.css')

Expand Down
3 changes: 3 additions & 0 deletions playground/css-codesplit/order/base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.order-bulk {
color: blue;
}
3 changes: 3 additions & 0 deletions playground/css-codesplit/order/dynamic.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.order-bulk {
color: green;
}
6 changes: 6 additions & 0 deletions playground/css-codesplit/order/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import './insert' // inserts "color: orange"
import './base.css' // includes "color: blue"

document.querySelector('.order-bulk-update').addEventListener('click', () => {
import('./dynamic.css') // includes "color: green"
})
3 changes: 3 additions & 0 deletions playground/css-codesplit/order/insert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const style = document.createElement('style')
style.textContent = '.order-bulk { color: orange; }'
document.head.appendChild(style)

0 comments on commit 4682524

Please sign in to comment.