nuxt: Nuxt does not clean up CSS after navigation (and injects CSS pre-navigation)
Environment
- Operating System:
Darwin - Node Version:
v16.19.0 - Nuxt Version:
3.6.5 - Nitro Version:
2.5.2 - Package Manager:
pnpm@8.3.1 - Builder:
vite - User Config:
extends,srcDir,build,hooks,runtimeConfig - Runtime Modules:
- - Build Modules:
-
Reproduction
https://stackblitz.com/edit/nuxt-starter-l1dvnf?file=app.vue
Describe the bug
There’s actually two manifestations of this bug.
First bug:
- Given two pages, A & B, and two layouts, X and Y
- Page A uses Template X
- Page B uses Template Y
- When navigating to page A, it will mount the CSS for Template X
- When navigating to page B, it will mount the CSS for Template Y
- However, when navigating back to page A, it will not remove the CSS for template Y.
- Bug: This means, effectively, that page A’s rendering is unstable, and will render differently depending on preceding navigation.
Second bug:
- Given the above, if you use pre-fetching with
NuxtLink(<NuxtLink>withoutnoPrefetch), then the CSS for template Y will be injected into the page when navigating to page A, even though it has no association with Template Y. - In other words, Nuxt eagerly injects CSS un-associated with the current page
Note that the first bug occurs whether or not you use noPrefetch.
Additional context
I originally thought this bug was associated with / the same bug as https://github.com/nuxt/nuxt/issues/3877, but was told that was not the case, so filing this new issue. I also thought it might be the exact same as this issue, but that issue is closed?
Logs
No response
About this issue
- Original URL
- State: open
- Created 10 months ago
- Reactions: 4
- Comments: 18 (6 by maintainers)
The behaviour here is not Nuxt’s but Vite’s; I would create a proposal or feature request there, that we can then benefit from in Nuxt.
While this is true for styles applied to individual pages, you cannot scope styles inside a layout, as this will not apply them to the pages using the layout… so the only real workaround is to encapsulate the layout styles in another parent selector (e.g. “.layout-a h1” and “.layout-b h1”) or using completely unique selectors.
this issue drove me insane when i was trying to reduce css bundle size by splitting them into different layouts. The second you use NuxtLink without disabling prefetching, the styles will get combined again and can cause unexpected behaviour.
It also didn’t help that this issue was closed, since it makes it more effort to find.
In general, I’m distressed that almost all of the major JavaScript SSR frameworks out there happen to have so many gotcha’s when handling css. It’s very hard to keep control and regularly lures me back to traditional SSR, where you have full control of the HTML for each page.
@matthew-dean No, absolutely not! 😋
IMO This is expected and you can use
<style scoped>(Scoped Styles) to avoid this. No styles will be “unloaded” when navigating. If your page has global styles that alter the whole application (non-scoped ones), they will stay throughout the user journey after being loaded unless somehow handled in userland ☺️The same applies to the issue mentioned above I’d say.
Fixed example using
:deep+ scoped styles.Happy for some other opinions here though (cc @danielroe)
I’m seeing this issue when not using layouts – simply two different pages. When I
@importwithin the<style></style>block of apage, Page A will keep the css files loaded from Page B after navigating B->A.apologies for the delay in looking at this.
@danielroe Or anyone? Any advice on how to work around this?
@danielroe If there’s a temporary workaround for this bug, I’d love to know! Thanks!