fix(tasks): update styles watcher to support chokidar v4#141
Conversation
|
Issues Found
|
|
Thanks for reviewing! changes made:
The glob import was already present on line 2, so nothing to add there. |
| absolute: true | ||
| }); | ||
|
|
||
| const watcher = chokidar.watch(files, { |
There was a problem hiding this comment.
Instead of creating a huge static list of paths with glob why not use something like this which translates to the previous behavior?
chokidar.watch(config.general.sourcesPath, {
ignored: (filePath, stats) => stats?.isFile() && !filePath.endsWith(`.${config.general.sourceKey}.scss`),
ignoreInitial: true
});
There was a problem hiding this comment.
I saw the issue description after I left my comment. The why of the solution I think should be clearly stated also in the PR description in addition to the link to the issue.
The current proposal could seem to be the only alternative with chokidar.
| // Note: fast-glob resolves files once at startup, so newly created SCSS files | ||
| // won't be picked up by the watcher without a restart. This is an accepted | ||
| // tradeoff to avoid EMFILE errors with recursive directory watching. | ||
| const files = await glob(pattern, { |
There was a problem hiding this comment.
For consistency and testing please try to reuse the generateEntries() util also for the watcher part.
The bellow example seem to work as intended:
const entries = generateEntries(config, 'scss');
// Build reverse map: absolute src path -> dest key
const srcToDest = Object.fromEntries(
Object.entries(entries).map(([dest, src]) => [src, dest])
);
const watcher = chokidar.watch(Object.values(entries), {
ignoreInitial: true
});
watcher.on('all', (event, file) => {
const destFile = srcToDest[file];
if (!destFile) return;
config.stylelint.failOnError = false;
renderStyles(file, destFile, config);
});
easingthemes
left a comment
There was a problem hiding this comment.
Approving — the async/await refactor is a real improvement and the fast-glob → array approach is the right shape for chokidar's post-v3 contract. Reuse of fast-glob (already used in utils/generateEntries.js) keeps the codebase consistent, and the inline comment about the new-file watcher limitation is the right call.
Left a few inline questions/suggestions — only the chokidar v5→v4 rationale (in package.json) is something I'd like clarified before merge; the rest are nice-to-haves or follow-ups.
| "autoprefixer": "^10.4.20", | ||
| "babel-loader": "9.1.2", | ||
| "chokidar": "^5.0.0", | ||
| "chokidar": "^4.0.3", |
There was a problem hiding this comment.
Why downgrade to v4 specifically rather than staying on ^5.0.0?
main is on chokidar ^5.0.0. Both v4 and v5 dropped glob support in watch(), so the file-array fix in this PR works equally well on either. The PR title says "support chokidar v4" but this is technically a downgrade from what's currently on main.
Given the previous attempt was reverted (f5df235), reviewers will want the rationale spelled out — Node engine constraint? Aligning with the sass transitive? Something v5 broke? Or alternatively, keep ^5.0.0 since the new code is forward-compatible.
This is the one item I'd like resolved before merge.
| const files = await glob(pattern, { | ||
| cwd: config.general.sourcesPath, | ||
| absolute: true | ||
| }); |
There was a problem hiding this comment.
Empty-array edge case. If glob(...) returns [] (e.g., a fresh project with no .source.scss files yet), chokidar.watch([]) is called and silently does nothing — while the log on line 11 still says "Watcher Sass / autoprefixer running...". A one-liner would help DX:
if (!files.length) {
log(__filename, 'No SCSS sources found to watch', '', 'warn');
}| renderStyles(file, destFile, config); | ||
| }); | ||
|
|
||
| } catch (e) { |
There was a problem hiding this comment.
Misleading catch message now that the try is wider. 'Something is missing, you need install dev dependencies for this.' made sense when require('chokidar') was the only failure mode. Now this also catches errors from await glob(...) (bad cwd, permissions, etc.).
Either narrow the try to just the require('chokidar'), or generalize the message — something like 'Failed to start SCSS watcher' would survive future refactors.
| .basename(file) | ||
| .replace(config.general.sourceKey, config.general.bundleKey); | ||
|
|
||
| const destFile = path.join(relativePath, fileName); |
There was a problem hiding this comment.
Pre-existing, out of scope but trivial while you're here: config.stylelint.failOnError = false is set inside the 'all' event handler, so it re-mutates config on every file-change event. It should be set once before watcher.on(...) is registered. Not introduced by this PR — just noticed it while reviewing. Up to you whether to roll it in or leave for a follow-up.
| Promise.allSettled(promises).then((results) => { | ||
| log(__filename, 'Styles done', '', 'info'); | ||
| resolve(); | ||
| module.exports = async (config) => { |
There was a problem hiding this comment.
Regression test? This is the second attempt at this fix after f5df235 was reverted. A small jest test that mocks fast-glob + chokidar and asserts chokidar.watch is called with an array (not a glob string) would lock in the behavior and prevent a third revert cycle. Happy to leave this as a follow-up issue if you'd prefer to keep this PR tight.
This PR fixes an issue with SCSS file watchers caused by Chokidar version > 3. In versions 4+, Chokidar no longer supports glob patterns directly.
Description
Chokidar v4 removed support for glob patterns in
watch().This PR updates the styles watcher to handle that breaking change by pre-resolving SCSS files via
fast-globbefore passing them to chokidar.Related Issue
Fixes #138
Types of changes
Checklist: