From 84c5b7e091eab1fb8536e2295285d911c9aa4005 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 29 Aug 2022 12:28:09 -0400 Subject: [PATCH] Reuse rule cache entries when possible --- src/lib/expandTailwindAtRules.js | 6 +-- src/lib/generateRules.js | 81 ++++++++++++++++++-------------- src/lib/setupContextUtils.js | 1 + 3 files changed, 49 insertions(+), 39 deletions(-) diff --git a/src/lib/expandTailwindAtRules.js b/src/lib/expandTailwindAtRules.js index a0c1635a0fba..30b470800626 100644 --- a/src/lib/expandTailwindAtRules.js +++ b/src/lib/expandTailwindAtRules.js @@ -177,16 +177,12 @@ export default function expandTailwindAtRules(context) { let classCacheCount = context.classCache.size env.DEBUG && console.time('Generate rules') - let rules = generateRules(candidates, context) + generateRules(candidates, context) env.DEBUG && console.timeEnd('Generate rules') // We only ever add to the classCache, so if it didn't grow, there is nothing new. env.DEBUG && console.time('Build stylesheet') if (context.stylesheetCache === null || context.classCache.size !== classCacheCount) { - for (let rule of rules) { - context.ruleCache.add(rule) - } - context.stylesheetCache = buildStylesheet([...context.ruleCache], context) } env.DEBUG && console.timeEnd('Build stylesheet') diff --git a/src/lib/generateRules.js b/src/lib/generateRules.js index 0f441fb18018..c99826e88971 100644 --- a/src/lib/generateRules.js +++ b/src/lib/generateRules.js @@ -649,8 +649,37 @@ function inKeyframes(rule) { return rule.parent && rule.parent.type === 'atrule' && rule.parent.name === 'keyframes' } +function getImportantStrategy(important) { + if (important === true) { + return (rule) => { + if (inKeyframes(rule)) { + return + } + + rule.walkDecls((d) => { + if (d.parent.type === 'rule' && !inKeyframes(d.parent)) { + d.important = true + } + }) + } + } + + if (typeof important === 'string') { + return (rule) => { + if (inKeyframes(rule)) { + return + } + + rule.selectors = rule.selectors.map((selector) => { + return `${important} ${selector}` + }) + } + } +} + function generateRules(candidates, context) { let allRules = [] + let strategy = getImportantStrategy(context.tailwindConfig.important) for (let candidate of candidates) { if (context.notClassCache.has(candidate)) { @@ -658,7 +687,11 @@ function generateRules(candidates, context) { } if (context.classCache.has(candidate)) { - allRules.push(context.classCache.get(candidate)) + continue + } + + if (context.candidateRuleCache.has(candidate)) { + allRules = allRules.concat(Array.from(context.candidateRuleCache.get(candidate))) continue } @@ -670,47 +703,27 @@ function generateRules(candidates, context) { } context.classCache.set(candidate, matches) - allRules.push(matches) - } - // Strategy based on `tailwindConfig.important` - let strategy = ((important) => { - if (important === true) { - return (rule) => { - rule.walkDecls((d) => { - if (d.parent.type === 'rule' && !inKeyframes(d.parent)) { - d.important = true - } - }) - } - } + let rules = context.candidateRuleCache.get(candidate) ?? new Set() + context.candidateRuleCache.set(candidate, rules) - if (typeof important === 'string') { - return (rule) => { - rule.selectors = rule.selectors.map((selector) => { - return `${important} ${selector}` - }) - } - } - })(context.tailwindConfig.important) + for (const match of matches) { + let [{ sort, layer, options }, rule] = match - return allRules.flat(1).map(([{ sort, layer, options }, rule]) => { - if (options.respectImportant) { - if (strategy) { + if (options.respectImportant && strategy) { let container = postcss.root({ nodes: [rule.clone()] }) - container.walkRules((r) => { - if (inKeyframes(r)) { - return - } - - strategy(r) - }) + container.walkRules(strategy) rule = container.nodes[0] } + + let newEntry = [sort | context.layerOrder[layer], rule] + rules.add(newEntry) + context.ruleCache.add(newEntry) + allRules.push(newEntry) } + } - return [sort | context.layerOrder[layer], rule] - }) + return allRules } function isArbitraryValue(input) { diff --git a/src/lib/setupContextUtils.js b/src/lib/setupContextUtils.js index b0552b05d50c..1fd72e301c4e 100644 --- a/src/lib/setupContextUtils.js +++ b/src/lib/setupContextUtils.js @@ -873,6 +873,7 @@ export function createContext(tailwindConfig, changedContent = [], root = postcs let context = { disposables: [], ruleCache: new Set(), + candidateRuleCache: new Map(), classCache: new Map(), applyClassCache: new Map(), notClassCache: new Set(),