Skip to content

Commit 59e003e

Browse files
Vite: Don't crash with virtual module dependencies (#16780)
Fixes #16732 If we can not get the mtime from a file, chances are that the resource is a virtual module. This is perfectly legit and we can fall back to what we did before the changes in `4.0.8` (which is to rebuild the root every time a change contains a dependency like that). ## Test plan Added a test to mimic the setup from the repor in #16732. Also ensured the repro now passes: <img width="1278" alt="Screenshot 2025-02-24 at 17 29 38" src="https://github.com/user-attachments/assets/d111273d-579f-44c2-82f5-aa32d6a1879a" /> Note that importing virtual modules directly in CSS does not work as the resolver we use does not resolve against the Vite runtime it seems. This is unrelated to the regression added in `4.0.8` though and something to look into in the future.
1 parent 37ea0c3 commit 59e003e

File tree

3 files changed

+19
-6
lines changed

3 files changed

+19
-6
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- _Experimental_: Add `user-valid` and `user-invalid` variants ([#12370](https://github.com/tailwindlabs/tailwindcss/pull/12370))
1414
- _Experimental_: Add `wrap-anywhere`, `wrap-break-word`, and `wrap-normal` utilities ([#12128](https://github.com/tailwindlabs/tailwindcss/pull/12128))
1515

16+
### Fixed
17+
18+
- Vite: Don't crash when importing a virtual module in JavaScript that ends in `.css` ([#16780](https://github.com/tailwindlabs/tailwindcss/pull/16780))
19+
1620
## [4.0.8] - 2025-02-21
1721

1822
### Added
2.28 KB
Binary file not shown.

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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,9 @@ class Root {
202202
private candidates: Set<string> = new Set<string>()
203203

204204
// List of all build dependencies (e.g. imported stylesheets or plugins) and
205-
// their last modification timestamp
206-
private buildDependencies = new Map<string, number>()
205+
// their last modification timestamp. If no mtime can be found, we need to
206+
// assume the file has always changed.
207+
private buildDependencies = new Map<string, number | null>()
207208

208209
constructor(
209210
private id: string,
@@ -334,14 +335,22 @@ class Root {
334335
}
335336

336337
private async addBuildDependency(path: string) {
337-
let stat = await fs.stat(path)
338-
this.buildDependencies.set(path, stat.mtimeMs)
338+
let mtime: number | null = null
339+
try {
340+
mtime = (await fs.stat(path)).mtimeMs
341+
} catch {}
342+
this.buildDependencies.set(path, mtime)
339343
}
340344

341345
private async requiresBuild(): Promise<boolean> {
342346
for (let [path, mtime] of this.buildDependencies) {
343-
let stat = await fs.stat(path)
344-
if (stat.mtimeMs > mtime) {
347+
if (mtime === null) return true
348+
try {
349+
let stat = await fs.stat(path)
350+
if (stat.mtimeMs > mtime) {
351+
return true
352+
}
353+
} catch {
345354
return true
346355
}
347356
}

0 commit comments

Comments
 (0)