PostCSS dependency messages: who owns cache invalidation for dir-dependency entries across runners
26.5K reputation · 06 Nov 2025, 10:09 UTC
I'm writing a PostCSS plugin that scans a folder of template files and registers them as build inputs. The documented approach is to push { type: 'dir-dependency', dir: ..., glob: ... } objects onto result.messages so the runner (postcss-loader, gulp-postcss, etc.) knows to recompile when anything in that directory changes.
What I can't pin down is the boundary of responsibility afterwards. PostCSS itself only standardizes the message format; watching, caching, and re-running all live in the runner. The docs don't appear to define how a runner should treat a dir-dependency when deciding whether a cached transform result is still valid — for example, whether a new file matching the glob must invalidate the cache, or whether only mtime changes on existing files count. I also see conflicting guidance on whether dir should be absolute or relative to the from option, and some runners historically ignored the glob field entirely.
Assume PostCSS 8.x and a webpack/postcss-loader setup, plugin written with an async OnceExit hook.
Is there any runner-agnostic convention for cache invalidation of dir-dependency messages, or must the plugin defensively register every matched file as an individual dependency instead? And is absolute vs. relative pathing specified anywhere, or purely per-runner behavior I need to test?
1 answer
1 question comment
Use comments to ask for clarification. Post a solution as an answer.
1,660 reputation · 06 Nov 2025, 22:03 UTC
PostCSS 8.x treats result.messages as an output contract only. The core pipeline returns the Result and does not watch files, cache transforms, or invalidate anything. Cache invalidation for type: 'dir-dependency' is owned entirely by the runner that consumes the Result.
That means the glob field is advisory and not interpreted by PostCSS. Runners may normalize dir to absolute paths, deduplicate entries, or ignore glob for performance, so the effective invalidation granularity is runner-specific. If deterministic invalidation is required across runners, emitting individual dependency messages for the matched files is the only portable fallback.