Repository navigation
perf: cache canonical classes and fix misaligned canonicalization - #20
Merged
Merged
Conversation
Tailwind dedupes canonicalizeCandidates output, so index-aligned results shifted and --fix rewrote valid classes. Canonicalize per candidate. Cache canonical forms in memory and on disk keyed by Tailwind version, rootFontSize and the local CSS import graph; spawn the worker only on a cache miss. Warm 400-file lint: 2094 ms -> ~500 ms.
1 task done
Address review of the disk cache: - untrack bench/.out and restore the test-env/ ignore line - the worker reports the files Tailwind read (compile onDependency); one stat stamp over them invalidates memory, disk and worker caches together - write-through merge on miss replaces the lossy exit-time flush - resolve the cache dir from ESLint cwd; fall back to tmpdir - key on plugin version and package versions of imported files
MaisonnatM
marked this pull request as ready for review
October 20, 2026 07:41
|
🎉 This PR is included in version 1.4.2 🎉 The release is available on: Your semantic-release bot 📦🚀 |
MaisonnatM
added a commit
that referenced
this pull request
Oct 20, 2026
* perf: append new canonical classes to the cache instead of rewriting it Each miss rewrote the whole table, so a cold run over 24k unique classes took 143 s instead of 24 s. * fix: key canonical cache on rem and engine version - Fold rootFontSize and the @tailwindcss/node version into the table key; drop per-package version walking. - Write the dependency manifest only when the worker reports a new file list. - Move resolveCacheDir next to the cache and key the in-memory cache on the cache dir. - Test that a warm disk cache never starts Tailwind. * refactor: one cache write path, atomic manifest, engine keyed as a file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
--fixcould rewrite valid classes to the wrong ones. In a 400-file benchmark, the old code reported 337 bogus warnings likeClass 'gap-2' should be 'bg-blue-500'. The rule was also slow: about 2.1 s on that project, against 0.37 s for ESLint with the rule off.What changed
canonicalizeCandidatesremoves duplicates from its output, so the result shifted against the input indexes whenever two classes canonicalized to the same value. The worker now canonicalizes one class at a time. A new integration case runs the real worker ongap-[8px] gap-2 p-2; it fails before this change and passes after.node_modules/.cache/eslint-plugin-tailwind-canonical-classes/under the ESLint cwd, or in the system temp directory when there is nonode_modules. The worker reports every file Tailwind read to load the CSS, viacompile'sonDependency. One mtime and size check over those files, run once per linted file, invalidates the in-memory, disk and worker caches together. That covers imported themes and npm upgrades, including in long-lived editors. Results are merged into the disk file on each miss, so concurrent linters add to the cache instead of overwriting each other.TAILWIND_CANONICAL_CLASSES_CACHE_DIRoverrides the location. The worker only starts on a cache miss.CallExpressiononly walks its ancestors when its callee is one of the configured utility functions (cn,clsx, ...). The CSS-not-found branch in the pipeline became unreachable, so it is removed.Measurement
npm run benchlints 400 JSX files with 40 elements each. Medians of 7 alternating runs on a loaded machine:Warnings match before and after, minus the misaligned ones.
Checks