Skip to content

Commit

Permalink
Reuse rule cache entries when possible
Browse files Browse the repository at this point in the history
  • Loading branch information
thecrypticace committed Aug 29, 2022
1 parent dacc723 commit 84c5b7e
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 39 deletions.
6 changes: 1 addition & 5 deletions src/lib/expandTailwindAtRules.js
Expand Up @@ -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')
Expand Down
81 changes: 47 additions & 34 deletions src/lib/generateRules.js
Expand Up @@ -649,16 +649,49 @@ 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)) {
continue
}

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
}

Expand All @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions src/lib/setupContextUtils.js
Expand Up @@ -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(),
Expand Down

0 comments on commit 84c5b7e

Please sign in to comment.