Skip to content

Commit 9f451ee

Browse files
authored
Cold start performance improvements (#20427)
<!-- 👋 Hey, thanks for your interest in contributing to Tailwind! **Please ask first before starting work on any significant new features.** It's never a fun experience to have your pull request declined after investing a lot of time and effort into a new feature. To avoid this from happening, we request that contributors create a discussion to first discuss any significant new features. For more info, check out the contributing guide: https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md --> ## Summary Hi guys, thanks for you great work! I work on performance improvements on https://github.com/schoero/eslint-plugin-better-tailwindcss project. Part of issues can be fixed on the tailwind side only. This is a first fix, I have a bigger one in mind, it would require a small additional public API method - out of scope of this PR. Please let me know what you think. ## Finding `getVariantOrder()` re-sorts all parsed variants with the (expensive) variant comparator on every call, and it is called by every compileCandidates() invocation — per build pass, per @apply substitution, and hundreds of times during candidate canonicalization via the variant signature caches. Since parsedVariants is append-only, the computed order only changes when a new variant is parsed, so we can cache the result and invalidate on parsedVariants.size. This makes cold canonicalization (IntelliSense, lint plugins) faster and removes repeated sorting from @apply substitution and incremental rebuilds. ## Test plan Tested at https://github.com/smnbbrv/better-tailwindcss-bench . The relevant part is the `epbt-now / tw-patched` **plugin cost** (ms, cold run net of parse baseline) | codebase | epbt-now / tw-now | epbt-patched / tw-now | epbt-now / tw-patched | epbt-patched / tw-patched | | ---------- | ----------------: | --------------------: | --------------------: | ------------------------: | | mixed | 6292 | 3965 (-37%) | 5395 (-14%) | 3595 (-43%) | | repetitive | 5279 | 2425 (-54%) | 4819 (-9%) | 2124 (-60%) | | unique | 6096 | 5458 (-10%) | 5507 (-10%) | 5295 (-13%) |
1 parent 90f8ff4 commit 9f451ee

1 file changed

Lines changed: 10 additions & 0 deletions

File tree

packages/tailwindcss/src/design-system.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ export function buildDesignSystem(
7575
let variants = createVariants(theme)
7676

7777
let parsedVariants = new DefaultMap((variant) => parseVariant(variant, designSystem))
78+
let cachedVariantOrder: Map<Variant, number> | null = null
79+
let cachedVariantOrderSize = -1
7880
let parsedCandidates = new DefaultMap((candidate) =>
7981
Array.from(parseCandidate(candidate, designSystem)),
8082
)
@@ -188,6 +190,11 @@ export function buildDesignSystem(
188190
},
189191

190192
getVariantOrder() {
193+
// parsedVariants only grows, so the cache should be reset only when the size changes
194+
if (cachedVariantOrder !== null && cachedVariantOrderSize === parsedVariants.size) {
195+
return cachedVariantOrder
196+
}
197+
191198
let variants = Array.from(parsedVariants.values())
192199
variants.sort((a, z) => this.variants.compare(a, z))
193200

@@ -209,6 +216,9 @@ export function buildDesignSystem(
209216
prevVariant = variant
210217
}
211218

219+
cachedVariantOrder = order
220+
cachedVariantOrderSize = parsedVariants.size
221+
212222
return order
213223
},
214224

0 commit comments

Comments
 (0)