-
-
Notifications
You must be signed in to change notification settings - Fork 7.6k
fix: css injection order with dynamic imports (#3924) #21079
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
cdbd666
89948cf
e9e76e6
2711e69
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -512,6 +512,28 @@ export const tests = (isLightningCSS: boolean) => { | |
| await expect.poll(() => getColor('.modules-pink')).toBe('pink') | ||
| }) | ||
|
|
||
| // Test for issue #3924: CSS injection order with diamond dependencies | ||
| test('async css order with diamond dependencies', async () => { | ||
| // Diamond dependency: main -> [chunk-a, chunk-b] -> shared-base | ||
| // Expected order: shared-base.css, chunk-a.css, chunk-b.css | ||
| // chunk-b.css should win (.diamond-test { color: green; background: yellow }) | ||
| await expect.poll(() => getColor('.diamond-test')).toBe('green') | ||
| await expect.poll(() => getBgColor('.diamond-test')).toBe('yellow') | ||
| }) | ||
|
|
||
| // Test for issue #9278: Shared function with global CSS before module CSS | ||
| test('async css order with shared dependency and global CSS', async () => { | ||
| // Both blue.js and black.js import make-text.js (shared dependency) | ||
| // Both import hotpink.css before their own module CSS | ||
| // Expected: hotpink.css should load first, then blue/black module CSS should win | ||
| // The elements have both .hotpink and their module class | ||
| const blueEl = await page.locator('text=async blue').first() | ||
| const blackEl = await page.locator('text=async black').first() | ||
|
|
||
| await expect.poll(() => getColor(blueEl)).toBe('blue') | ||
| await expect.poll(() => getColor(blackEl)).toBe('black') | ||
| }) | ||
|
Comment on lines
+524
to
+535
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test seems to pass without the changes. |
||
|
|
||
| test('@import scss', async () => { | ||
| expect(await getColor('.at-import-scss')).toBe('red') | ||
| }) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| import { makeText } from './make-text' | ||
| import './hotpink.css' | ||
| import styles from './black.module.css' | ||
|
|
||
| makeText(styles['black-module'], 'async black') |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| .black-module { | ||
| color: black; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| import { makeText } from './make-text' | ||
| import './hotpink.css' | ||
| import styles from './blue.module.css' | ||
|
|
||
| makeText(styles['blue-module'], 'async blue') |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| .blue-module { | ||
| color: blue; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| /* Chunk A depends on shared-base */ | ||
| /* This should come AFTER shared-base.css */ | ||
| .diamond-test { | ||
| color: blue; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { initSharedBase } from './shared-base' | ||
| import './chunk-a.css' | ||
|
|
||
| initSharedBase() | ||
|
|
||
| export function initChunkA() { | ||
| console.log('[chunk-a] initialized') | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| /* Chunk B also depends on shared-base */ | ||
| /* This should come AFTER shared-base.css AND chunk-a.css */ | ||
| .diamond-test { | ||
| color: green; | ||
| background: yellow; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import { initSharedBase } from './shared-base' | ||
| import { initChunkA } from './chunk-a' | ||
| import './chunk-b.css' | ||
|
|
||
| initSharedBase() | ||
| initChunkA() | ||
|
|
||
| export function initChunkB() { | ||
| console.log('[chunk-b] initialized') | ||
|
|
||
| // Create test element | ||
| const div = document.createElement('div') | ||
| div.className = 'diamond-test' | ||
| div.textContent = 'Diamond Dependency Test' | ||
| document.body.appendChild(div) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // This creates a diamond dependency: | ||
| // main (this file) | ||
| // -> chunk-a -> shared-base | ||
| // -> chunk-b -> shared-base | ||
| // -> chunk-a -> shared-base | ||
| // | ||
| // Expected CSS order: shared-base.css, chunk-a.css, chunk-b.css | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not the expected order. There's no expected order in this case. It depends on which file is sent to the browser first. |
||
| // Expected final color: green (from chunk-b) | ||
| // Expected final background: yellow (from chunk-b) | ||
|
|
||
| Promise.all([import('./chunk-a.js'), import('./chunk-b.js')]).then( | ||
| ([modA, modB]) => { | ||
| modA.initChunkA() | ||
| modB.initChunkB() | ||
| }, | ||
| ) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned above, this test asserts a case that shouldn't be asserted. So this test should be removed.