Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI: Ignore watch events for files that don't match globs #9215

Merged
merged 4 commits into from Aug 31, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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