Skip to content

Commit

Permalink
CLI: Ignore watch events for files that don't match globs (#9215)
Browse files Browse the repository at this point in the history
* Don’t re-add files in the CLI watcher that are covered by dynamic patterns

They don’t have the same problem. As long as the parent directory is watched their add/change events will fire correctly

* Ignore raw events for files that don’t match the content files

* fixup

* Update changelog
  • Loading branch information
thecrypticace committed Aug 31, 2022
1 parent edf47a0 commit 8b1bf80
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -21,7 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Sort tags before classes when `@applying` a selector with joined classes ([#9107](https://github.com/tailwindlabs/tailwindcss/pull/9107))
- Remove invalid `outline-hidden` utility ([#9147](https://github.com/tailwindlabs/tailwindcss/pull/9147))
- Honor the `hidden` attribute on elements in preflight ([#9174](https://github.com/tailwindlabs/tailwindcss/pull/9174))
- Don't stop watching atomically renamed files ([#9173](https://github.com/tailwindlabs/tailwindcss/pull/9173))
- Don't stop watching atomically renamed files ([#9173](https://github.com/tailwindlabs/tailwindcss/pull/9173), [#9215](https://github.com/tailwindlabs/tailwindcss/pull/9215))
- Re-use existing entries in the rule cache ([#9208](https://github.com/tailwindlabs/tailwindcss/pull/9208))
- Don't output duplicate utilities ([#9208](https://github.com/tailwindlabs/tailwindcss/pull/9208))
- Fix `fontFamily` config TypeScript types ([#9214](https://github.com/tailwindlabs/tailwindcss/pull/9214))
Expand Down
37 changes: 34 additions & 3 deletions src/cli.js
Expand Up @@ -17,6 +17,7 @@ import getModuleDependencies from './lib/getModuleDependencies'
import log from './util/log'
import packageJson from '../package.json'
import normalizePath from 'normalize-path'
import micromatch from 'micromatch'
import { validateConfig } from './util/validateConfig.js'

let env = {
Expand Down Expand Up @@ -837,6 +838,23 @@ async function build() {
}

let config = refreshConfig(configPath)
let contentPatterns = refreshContentPatterns(config)

/**
* @param {import('../types/config.js').RequiredConfig} config
* @return {{all: string[], dynamic: string[], static: string[]}}
**/
function refreshContentPatterns(config) {
let globs = extractFileGlobs(config)
let tasks = fastGlob.generateTasks(globs, { absolute: true })
let dynamicPatterns = tasks.filter((task) => task.dynamic).flatMap((task) => task.patterns)
let staticPatterns = tasks.filter((task) => !task.dynamic).flatMap((task) => task.patterns)

return {
all: [...staticPatterns, ...dynamicPatterns],
dynamic: dynamicPatterns,
}
}

if (input) {
contextDependencies.add(path.resolve(input))
Expand Down Expand Up @@ -867,6 +885,7 @@ async function build() {
env.DEBUG && console.time('Resolve config')
context = null
config = refreshConfig(configPath)
contentPatterns = refreshContentPatterns(config)
env.DEBUG && console.timeEnd('Resolve config')

env.DEBUG && console.time('Watch new files')
Expand Down Expand Up @@ -924,7 +943,14 @@ async function build() {
// Restore watching any files that are "removed"
// This can happen when a file is pseudo-atomically replaced (a copy is created, overwritten, the old one is unlinked, and the new one is renamed)
// TODO: An an optimization we should allow removal when the config changes
watcher.on('unlink', (file) => watcher.add(file))
watcher.on('unlink', (file) => {
file = normalizePath(file)

// Only re-add the file if it's not covered by a dynamic pattern
if (!micromatch.some([file], contentPatterns.dynamic)) {
watcher.add(file)
}
})

// Some applications such as Visual Studio (but not VS Code)
// will only fire a rename event for atomic writes and not a change event
Expand All @@ -935,11 +961,16 @@ async function build() {
return
}

let watchedPath = path.resolve(meta.watchedPath)
let watchedPath = meta.watchedPath

// Watched path might be the file itself
// Or the directory it is in
filePath = watchedPath.endsWith(filePath) ? watchedPath : path.resolve(watchedPath, filePath)
filePath = watchedPath.endsWith(filePath) ? watchedPath : path.join(watchedPath, filePath)

// Skip this event since the files it is for does not match any of the registered content globs
if (!micromatch.some([filePath], contentPatterns.all)) {
return
}

// Skip since we've already queued a rebuild for this file that hasn't happened yet
if (pendingRebuilds.has(filePath)) {
Expand Down

0 comments on commit 8b1bf80

Please sign in to comment.