Skip to content

Commit d4d89b9

Browse files
sapphi-redpatak-dev
authored andcommitted
fix(css): backport #7746
1 parent da77dee commit d4d89b9

File tree

7 files changed

+59
-10
lines changed

7 files changed

+59
-10
lines changed

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,31 @@
11
import { findAssetFile, getColor, isBuild, readManifest } from '../../testUtils'
22

3-
test('should load both stylesheets', async () => {
3+
test('should load all stylesheets', async () => {
44
expect(await getColor('h1')).toBe('red')
55
expect(await getColor('h2')).toBe('blue')
6+
expect(await getColor('.dynamic')).toBe('green')
7+
})
8+
9+
test('should load dynamic import with inline', async () => {
10+
const css = await page.textContent('.dynamic-inline')
11+
expect(css).toMatch('.inline')
12+
13+
expect(await getColor('.inline')).not.toBe('yellow')
14+
})
15+
16+
test('should load dynamic import with module', async () => {
17+
const css = await page.textContent('.dynamic-module')
18+
expect(css).toMatch('_mod_')
19+
20+
expect(await getColor('.mod')).toBe('yellow')
621
})
722

823
if (isBuild) {
924
test('should remove empty chunk', async () => {
1025
expect(findAssetFile(/style.*\.js$/)).toBe('')
1126
expect(findAssetFile('main.*.js$')).toMatch(`/* empty css`)
1227
expect(findAssetFile('other.*.js$')).toMatch(`/* empty css`)
28+
expect(findAssetFile(/async.*\.js$/)).toBe('')
1329
})
1430

1531
test('should generate correct manifest', async () => {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.dynamic {
2+
color: green;
3+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,11 @@
1+
<h1>This should be red</h1>
2+
<h2>This should be blue</h2>
3+
4+
<p class="dynamic">This should be green</p>
5+
<p class="inline">This should not be yellow</p>
6+
<p class="dynamic-inline"></p>
7+
<p class="mod">This should be yellow</p>
8+
<p class="dynamic-module"></p>
9+
110
<script type="module" src="/main.js"></script>
211
<div id="app"></div>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.inline {
2+
color: yellow;
3+
}
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import './style.css'
22
import './main.css'
33

4-
document.getElementById(
5-
'app'
6-
).innerHTML = `<h1>This should be red</h1><h2>This should be blue</h2>`
4+
import('./async.css')
5+
6+
import('./inline.css?inline').then((css) => {
7+
document.querySelector('.dynamic-inline').textContent = css.default
8+
})
9+
10+
import('./mod.module.css').then((css) => {
11+
document.querySelector('.dynamic-module').textContent = JSON.stringify(
12+
css.default
13+
)
14+
document.querySelector('.mod').classList.add(css.default.mod)
15+
})
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.mod {
2+
color: yellow;
3+
}

packages/vite/src/node/plugins/importAnalysisBuild.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
152152
d: dynamicIndex
153153
} = imports[index]
154154

155+
const isDynamic = dynamicIndex > -1
156+
155157
// import.meta.glob
156158
if (
157159
source.slice(start, end) === 'import.meta' &&
@@ -189,11 +191,13 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
189191
continue
190192
}
191193

192-
if (dynamicIndex > -1 && insertPreload) {
194+
if (isDynamic && insertPreload) {
193195
needPreloadHelper = true
194-
const original = source.slice(expStart, expEnd)
195-
const replacement = `${preloadMethod}(() => ${original},${isModernFlag}?"${preloadMarker}":void 0)`
196-
str().overwrite(expStart, expEnd, replacement, { contentOnly: true })
196+
str().prependLeft(expStart, `${preloadMethod}(() => `)
197+
str().appendRight(
198+
expEnd,
199+
`,${isModernFlag}?"${preloadMarker}":void 0)`
200+
)
197201
}
198202

199203
// Differentiate CSS imports that use the default export from those that
@@ -203,12 +207,14 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
203207
if (
204208
specifier &&
205209
isCSSRequest(specifier) &&
206-
source.slice(expStart, start).includes('from') &&
210+
// always inject ?used query when it is a dynamic import
211+
// because there is no way to check whether the default export is used
212+
(source.slice(expStart, start).includes('from') || isDynamic) &&
207213
// edge case for package names ending with .css (e.g normalize.css)
208214
!(bareImportRE.test(specifier) && !specifier.includes('/'))
209215
) {
210216
const url = specifier.replace(/\?|$/, (m) => `?used${m ? '&' : ''}`)
211-
str().overwrite(start, end, dynamicIndex > -1 ? `'${url}'` : url, {
217+
str().overwrite(start, end, isDynamic ? `'${url}'` : url, {
212218
contentOnly: true
213219
})
214220
}

0 commit comments

Comments
 (0)