You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Open the network tab and throttle your network to something like "Slow 3G"
Refresh the page and notice that the styles for some sections are loaded after page load, causing FOUC and CLS
Look at the page source
notice that there is a <style> tag in the <head> containing ONLY the (correctly) inlined styles of the WorkingLocalComponent
notice there are no other styles included in the head
Look at the network requests and notice that there is an index.[hash].css file that is loaded, except the initiator for this is a .js file.
Describe the bug
When a page contains a component that's used multiple times, including once inside a lazy-component on the same page, nuxt will fail to correctly inject the styles that are imported by other components on the page.
The bug manifests when the styles are imported in the JS code, and not if they are part of the SFC's <style> tag. Please see the "Additional context" section for why this is important.
There are actually two different aspects of this bug:
style files imported in components that are exported as JS modules by a third-party library
the bug will always manifest
style files imported in components on the same Nuxt repo
the bug will manifest if the imported file requires a pre-processor like LESS or SASS (not for plain CSS files)
This is a very complex set of circumstances, so I will try to explain using the components used in the reproduction repository.
ReusedComponent - its contents is irrelevant, you can imagine it as very simple component, including even something like a "terms" fine print block.
the important part is that this component is used as-is on the page itself, but also rendered inside a lazy-loaded component
ComplexComponent - this is an optional component that might eventually get rendered; it includes ReusedComponent
the important part is that it's included on the page using the <lazy prefix
WorkingLocalComponent - this is a component that imports a .css file in the <script> section
this is unaffected by the bug
the styles in the CSS file are correctly inlined in the server-rendered HTML
BrokenLocalComponent - this is a component that imports a .less file in the <script> section
the styles in the LESS file are not inlined in the HTML
they are processed and extracted in the index.[hash].css file that gets injected in the document by a .js file on page load
with regards to the library's internal code structure
the styles for this particular component are extracted in the dist/assets/One.css file, BUT:
that file is imported in dist/components/buttons/One.js so there is no overhead for the developers to manually import styles
with regards to the nuxt build:
the styles for this component are not inlined by Nuxt in the server-rendered HTML
they are extracted in the index.[hash].css file that gets injected in the document by a .js file on page load
Interesting tid-bits
Ways to make the bug go away (neither of which are really acceptable solutions):
remove ReusedComponent from ComplexComponent, or
use ComplexComponent on the page in a classic fashion (not "lazy")
In both of the situations above, the index.[hash].css file is included as a <link rel="stylesheet" in the <head>
this partially solves the FOUC issue but is suboptimal
it's peculiar that the styles are not inlined in a <style> tag
Expected behaviour
Any styles for components that are rendered on the page on load should be inlined in the <style> tag
Additional context
This is most relevant in the case of UI libraries that compile their components into JS files where the styles specific to each component are imported (e.g. using the vite-plugin-lib-inject-css plugin).
We generated a minimal demo library here, and you can see the aspect of the build code in the dist/components/button/One.js file, which imports dist/assets/One.css including the styles specific only to that particular component.
Logs
No response
The text was updated successfully, but these errors were encountered:
Environment
Nuxt project info: 19:03:45
Reproduction
Minimal reproduction here
pnpm run build && pnpm run preview
<style>
tag in the<head>
containing ONLY the (correctly) inlined styles of theWorkingLocalComponent
index.[hash].css
file that is loaded, except the initiator for this is a.js
file.Describe the bug
When a page contains a component that's used multiple times, including once inside a lazy-component on the same page, nuxt will fail to correctly inject the styles that are imported by other components on the page.
The bug manifests when the styles are imported in the JS code, and not if they are part of the SFC's
<style>
tag. Please see the "Additional context" section for why this is important.There are actually two different aspects of this bug:
This is a very complex set of circumstances, so I will try to explain using the components used in the reproduction repository.
ReusedComponent
- its contents is irrelevant, you can imagine it as very simple component, including even something like a "terms" fine print block.ComplexComponent
- this is an optional component that might eventually get rendered; it includesReusedComponent
<lazy
prefixWorkingLocalComponent
- this is a component that imports a.css
file in the<script>
sectionBrokenLocalComponent
- this is a component that imports a.less
file in the<script>
sectionindex.[hash].css
file that gets injected in the document by a.js
file on page loadOne
- this is a component that's part of a third-party Vue librarydist/assets/One.css
file, BUT:dist/components/buttons/One.js
so there is no overhead for the developers to manually import stylesindex.[hash].css
file that gets injected in the document by a.js
file on page loadInteresting tid-bits
ReusedComponent
fromComplexComponent
, orComplexComponent
on the page in a classic fashion (not "lazy")index.[hash].css
file is included as a<link rel="stylesheet"
in the<head>
<style>
tagExpected behaviour
Any styles for components that are rendered on the page on load should be inlined in the
<style>
tagAdditional context
This is most relevant in the case of UI libraries that compile their components into JS files where the styles specific to each component are imported (e.g. using the
vite-plugin-lib-inject-css
plugin).We generated a minimal demo library here, and you can see the aspect of the build code in the
dist/components/button/One.js
file, which importsdist/assets/One.css
including the styles specific only to that particular component.Logs
No response
The text was updated successfully, but these errors were encountered: