Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get emotion cache by key #3266

Open
targetlucked69 opened this issue Oct 16, 2024 · 5 comments
Open

Get emotion cache by key #3266

targetlucked69 opened this issue Oct 16, 2024 · 5 comments

Comments

@targetlucked69
Copy link

targetlucked69 commented Oct 16, 2024

The problem

Get cache by key so userland can manually clear a cache even if the external component doesnt export it.

Say there's an external component library named awesome-lib that exports components that uses @emotion/react with custom cache, and you're using Astro's View transition - the styles will be removed when navigating. A trick would be to clear the emotion cache used, but awesome-lib doesn't export it.

Proposed solution

import { getCache } from '@emotion/css' // or from @emotion/react?
 
document.addEventListener('astro:before-swap', () => {
  const cache = getCache({ key: 'internal-key' })
  cache.sheet.flush();
  cache.inserted = {};
  cache.registered = {};
})

Is there already an existing function that does this?

@Andarist
Copy link
Member

I'm rather hesitant to expose this as those keys were never meant to be a public API - just a mechanism to deconflict styles between caches. I think awesome-lib should export a clean-up function here or Astro shouldn't remove the styles like this. Our styles are somewhat idempotent - even if you leave a page that used some styles, you can leave them in the DOM as they might still come useful when you get back to displaying the components depending on them.

@targetlucked69
Copy link
Author

targetlucked69 commented Oct 17, 2024

Thanks for the reply @Andarist. I tried this solution suggested by a maintainer from Astro:

document.addEventListener('astro:before-swap', e => {
  const el = document.querySelector('style[data-emotion]').cloneNode(true)
  e.newDocument.head.appendChild(el)
});

This clones the existing <style data-emotion></style> element in the head and puts it to the next document (e.newDocument), but somehow the styles aren't applied. Does emotion have some kind of mutationobserver and somewhat gets confused with this logic? The only thing that worked is clearing the emotion cache.

Do you know of any other trick that can clear the cache without awesome-lib exposing anything?

@Andarist
Copy link
Member

The likely problem is that the memory is still preserved between those navigations so Emotion things those elements are still in the DOM as they are still registered in the cache.

I think the above solution tries to work around the problem. Astro is removing a resource (style element) from a shared resource (DOM). This is not a resource they control (they have not created it) so its lifecycle (like cleaning up/removing from the DOM) doesn't belong to their responsibilities.

I suspect cleaning up the whole DOM is deeply integrated in their philosophy and implementation. So I think, at the very least, they should have some opt-out mechanism from this cleanup, like a data-attribute or smth. This way you could just set that - without being concerned with cache keys etc and they would just leave those elements alone.

@targetlucked69
Copy link
Author

they should have some opt-out mechanism from this cleanup, like a data-attribute or smth

If they do have a data-attribute that keeps it from being removed in the DOM, do you mean apply that data-attribute to the <style data-emotion></style> element created by emotion?

@Andarist
Copy link
Member

Yeah, exactly. I can't add it to Emotion because any data attribute they might have is kinda theirs and I don't want to depend on it directly. But it can easily by applied by you - the person who integrates both tools. I with this wouldn't be required at all but I don't see a different path forward here right now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants