Skip to content

Non-Deterministic CSS ordering for extracted CSS in an SSR App #8825

Closed
@brophdawg11

Description

@brophdawg11

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:

  1. 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.
  2. 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.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions