Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Handle `'` syntax in ClojureScript when extracting classes ([#18888](https://github.com/tailwindlabs/tailwindcss/pull/18888))
- Handle `@variant` inside `@custom-variant` ([#18885](https://github.com/tailwindlabs/tailwindcss/pull/18885))
- Merge suggestions when using `@utility` ([#18900](https://github.com/tailwindlabs/tailwindcss/pull/18900))
- Ensure that file system watchers created when using the CLI are always cleaned up ([#18905](https://github.com/tailwindlabs/tailwindcss/pull/18905))

## [4.1.13] - 2025-09-03

Expand Down
16 changes: 8 additions & 8 deletions packages/@tailwindcss-cli/src/commands/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,9 @@ export async function handle(args: Result<ReturnType<typeof options>>) {

// Watch for changes
if (args['--watch']) {
let cleanupWatchers = await createWatchers(
watchDirectories(scanner),
async function handle(files) {
let cleanupWatchers: (() => Promise<void>)[] = []
cleanupWatchers.push(
await createWatchers(watchDirectories(scanner), async function handle(files) {
try {
// If the only change happened to the output file, then we don't want to
// trigger a rebuild because that will result in an infinite loop.
Expand Down Expand Up @@ -304,15 +304,15 @@ export async function handle(args: Result<ReturnType<typeof options>>) {

// Setup new watchers
DEBUG && I.start('Setup new watchers')
let newCleanupWatchers = await createWatchers(watchDirectories(scanner), handle)
let newCleanupFunction = await createWatchers(watchDirectories(scanner), handle)
DEBUG && I.end('Setup new watchers')

// Clear old watchers
DEBUG && I.start('Cleanup old watchers')
await cleanupWatchers()
await Promise.all(cleanupWatchers.splice(0).map((cleanup) => cleanup()))
DEBUG && I.end('Cleanup old watchers')

cleanupWatchers = newCleanupWatchers
cleanupWatchers.push(newCleanupFunction)

// Re-compile the CSS
DEBUG && I.start('Build CSS')
Expand Down Expand Up @@ -362,14 +362,14 @@ export async function handle(args: Result<ReturnType<typeof options>>) {
eprintln(err.toString())
}
}
},
}),
)

// Abort the watcher if `stdin` is closed to avoid zombie processes. You can
// disable this behavior with `--watch=always`.
if (args['--watch'] !== 'always') {
process.stdin.on('end', () => {
cleanupWatchers().then(
Promise.all(cleanupWatchers.map((fn) => fn())).then(
() => process.exit(0),
() => process.exit(1),
)
Expand Down