Naming is hard so I took this name from the React hook 😎
Also use this useMemoy utility to make sure that the extractUtilityNames
is cached. There is no need to re-compute the utility names all the
time.
We used to clone the full tree and then remove all the children, this
was a bit too slow so therefore we will now create a new tree based on
the old information.
We alreayd know that we have an `@apply` otherwise we would not have
called that function in the first place. Moving to a `do {} while ()`
allows us to skip 1 call to `hasAtRule(css, 'apply')`. Which is nice
because that skips a possible full traversal.
We create a big lookup table so that we can lookup the nodes by its
utilityName. This is used inside the recursive `@apply` code.
This big lookup table will clone every single rule and put it in,
however we don't need to clone everything! We are only interested in the
rules that have been actually applied.
This way we make the cloning of the rule lazy and only when we use this
exact rule.
There is an additional performace "issue" though: When we read the same
rule multiple times, it will clone every time you read from that object.
We could add additional memoization stuff, but so far it doesn't seem to
be the bottleneck. Therefore I've added a perf todo just to leave a mark
when this becomes the bottleneck.
Currently we will walk the tree for every single rule to see if an
`@apply` exists somewhere in that tree. However we don't use the
`containsApply` anymore so this is a quick win!
We were re-creating the classNameParser inside the loop. Since that code
is all pretty pure we can hoist it so that we don't have to recreate
that parser all the time.
There is no need in re-compiling tailwind or building expensive lookupt
tables when it turns out that we don't even need it.
We have a small overhead by walking the tree to check if `@apply`
exists. However this outweighs the slowness of re-generating tailwind +
expensive lookup tables.