Skip to content

Commit fac8f7d

Browse files
Vite: Emit build dependencies on partial rebuilds (#17347)
Closes #17339 This PR fixes an issue that caused changes to `@import`-ed CSS files to no longer rebuild the stylesheet after a change was made to a template file. The change in the template file causes a fast-path in the Vite plugin now after changes in 4.0.8: _partial rebuilds_. For that branch we do not need to re-evaluate your input CSS since we know only the candidate list changed. However, we still need to emit all build dependencies as via `addWatchFile(…)`, otherwise Vite will not correctly register updates for these dependencies anymore. ## Test plan - Updated the kitchen-sink Vite update tests to ensure that an `@import`-ed CSS file can be updated even after a partial rebuild. - Ensure this works in our Vite playground
1 parent 42f68bb commit fac8f7d

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424

2525
### Fixed
2626

27+
- Vite: Ensure that updates to an imported CSS file are properly propagated after updating templates ([#17347](https://github.com/tailwindlabs/tailwindcss/pull/17347))
2728
- Fix class extraction followed by `(` in Pug ([#17320](https://github.com/tailwindlabs/tailwindcss/pull/17320))
2829

2930
### [4.0.15] - 2025-03-20

integrations/vite/index.test.ts

+48
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,15 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
149149
'project-a/src/index.css': css`
150150
@reference 'tailwindcss/theme';
151151
@import 'tailwindcss/utilities';
152+
@import './imported.css';
152153
@config '../tailwind.config.js';
153154
@source '../../project-b/src/**/*.html';
154155
`,
156+
'project-a/src/imported.css': css`
157+
.imported {
158+
color: red;
159+
}
160+
`,
155161
'project-b/src/index.html': html`
156162
<div class="flex" />
157163
`,
@@ -179,6 +185,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
179185
expect(styles).toContain(candidate`underline`)
180186
expect(styles).toContain(candidate`flex`)
181187
expect(styles).toContain(candidate`font-bold`)
188+
expect(styles).toContain(candidate`imported`)
182189
})
183190

184191
await retryAssertion(async () => {
@@ -199,6 +206,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
199206
expect(styles).toContain(candidate`underline`)
200207
expect(styles).toContain(candidate`flex`)
201208
expect(styles).toContain(candidate`font-bold`)
209+
expect(styles).toContain(candidate`imported`)
202210
expect(styles).toContain(candidate`m-2`)
203211
})
204212

@@ -216,6 +224,7 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
216224
expect(styles).toContain(candidate`underline`)
217225
expect(styles).toContain(candidate`flex`)
218226
expect(styles).toContain(candidate`font-bold`)
227+
expect(styles).toContain(candidate`imported`)
219228
expect(styles).toContain(candidate`m-2`)
220229
expect(styles).toContain(candidate`[.changed_&]:content-['project-b/src/index.js']`)
221230
})
@@ -234,13 +243,52 @@ describe.each(['postcss', 'lightningcss'])('%s', (transformer) => {
234243
`,
235244
)
236245

246+
let styles = await fetchStyles(url)
247+
expect(styles).toContain(candidate`red`)
248+
expect(styles).toContain(candidate`flex`)
249+
expect(styles).toContain(candidate`imported`)
250+
expect(styles).toContain(candidate`m-2`)
251+
expect(styles).toContain(candidate`underline`)
252+
expect(styles).toContain(candidate`[.changed_&]:content-['project-b/src/index.js']`)
253+
expect(styles).toContain(candidate`font-bold`)
254+
})
255+
256+
await retryAssertion(async () => {
257+
// Trigger a partial rebuild for the next test
258+
await fs.write(
259+
'project-a/index.html',
260+
html`
261+
<head>
262+
<link rel="stylesheet" href="./src/index.css" />
263+
</head>
264+
<body>
265+
<div class="m-4">Hello, world!</div>
266+
</body>
267+
`,
268+
)
269+
let styles = await fetchStyles(url)
270+
expect(styles).toContain(candidate`m-4`)
271+
})
272+
273+
await retryAssertion(async () => {
274+
// Changing an `@imported` CSS file after a partial rebuild also triggers the correct update
275+
await fs.write(
276+
'project-a/src/imported.css',
277+
css`
278+
.imported-updated {
279+
color: red;
280+
}
281+
`,
282+
)
283+
237284
let styles = await fetchStyles(url)
238285
expect(styles).toContain(candidate`red`)
239286
expect(styles).toContain(candidate`flex`)
240287
expect(styles).toContain(candidate`m-2`)
241288
expect(styles).toContain(candidate`underline`)
242289
expect(styles).toContain(candidate`[.changed_&]:content-['project-b/src/index.js']`)
243290
expect(styles).toContain(candidate`font-bold`)
291+
expect(styles).toContain(candidate`imported-updated`)
244292
})
245293
},
246294
)

packages/@tailwindcss-vite/src/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ class Root {
277277

278278
this.scanner = new Scanner({ sources })
279279
DEBUG && I.end('Setup scanner')
280+
} else {
281+
for (let buildDependency of this.buildDependencies.keys()) {
282+
addWatchFile(buildDependency)
283+
}
280284
}
281285

282286
if (

0 commit comments

Comments
 (0)