Description
Version
2.5.17
Reproduction link
https://github.com/brophdawg11/vue-ssr-css-ordering
Steps to reproduce
Reproduction steps are outlined in the README in the github repo.
What is expected?
In both development and production builds, the extracted CSS stylesheets should be loaded in a deterministic order.
I believe from reading various semi-related github issues that the order corresponds with the import order via webpack. If that is the case for SSR as well, I would expect the order to be app.css -> home.css -> about.css
since the App.vue
file is loaded statically, and Home.vue
and About.vue
are loaded dynamically via routes in that order.
Either way, I would expect global styles from App.vue
to always be loaded first, followed by dynamic-route styles, allowing for a proper cascade.
What is actually happening?
I think there are two issues at play:
Primary Issue: In development mode, the app.css
file is incorrectly loaded after the about.css
file, breaking the cascade for contents of About.vue
.
Secondary Issue: In production mode, the app.css
file is properly loaded first, but then about.css
is loaded prior to home.css
even though they are imported in the reverse order and even when SSR-ing the home page.
Additional Notes
I'm trying to determine what feels like the optimal solution, and I think there are a few options, in a loose descending order of "optimal", and likely increasing order of feasibility:
- Global styles from the root
App.vue
component would always be loaded first, followed by the only the styles for the component matched for the current route. Additional route-specific styles would be loaded on demand when routing. I understand this is likely beyond the scope of the bundle renderer and potentially something to be implemented by the application itself. - Global styles from the root
App.vue
component would always be loaded first, followed by styles for the current route-component, followed by styles for additional route-components. - Global styles from the root
App.vue
component would always be loaded first, followed by styles for route-level components, in import-order (i.e., in route-declaration order)
It is also worth noting that my specific scenario in my larger app is slightly different, but I wasn't able to quite reproduce it exactly in this minimal repo, and I'm not quite sure why. In my specific app case, I have an App.vue
and 3 dynamic routes defined in the order:
- Home
- Page 1
- Page 2
In development mode, my stylesheets are included in the order: page1, app, home, page2.
In production mode, my stylesheets are included in the order: home, page1, page2, app
So in the demo repo, the production build is correct insofar as it doesn't break the cascade for either route, and the development build is incorrect for only one of the routes.
In my actual app, the development mode only breaks the cascade for the page1 route, while the production build breaks it for all routes.