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

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

Closed
brophdawg11 opened this issue Sep 21, 2018 · 6 comments
Closed

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

brophdawg11 opened this issue Sep 21, 2018 · 6 comments

Comments

@brophdawg11
Copy link

brophdawg11 commented Sep 21, 2018

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.

@brophdawg11
Copy link
Author

I think the only workaround available at the moment is to set inject:false on the bundle renderer and manually insert these into the template in the proper order by reading them from the client manifest? I assume that even using renderStyles from https://ssr.vuejs.org/guide/build-config.html#manual-asset-injection would result in the same ordering issues?

@lyswhut
Copy link

lyswhut commented Dec 13, 2018

I also encountered this problem. I extracted CSS with mini-css-extract-plugin. After compiling via webpack, there will be a CSS file for every chunk, but VUE-SSR does not seem to support CSS asynchronous chunk loading. I don't have The way to make a mini-css-extract-plugin create a single CSS file:

webpack-contrib/mini-css-extract-plugin#52

In VUE-SSR, the CSS module is loaded synchronously, the JS module is loaded asynchronously, and the CSS module loading order is reversed:
ssr

In SPA, CSS modules and JS modules are loaded asynchronously:
spa

@iztsv
Copy link

iztsv commented Feb 13, 2019

@lyswhut

VUE-SSR does not seem to support CSS asynchronous chunk loading

that problem was fixed in v2.5.18-beta.0 - #7902

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

I have the same issue in 2.5.22

@brophdawg11
Copy link
Author

brophdawg11 commented Feb 18, 2019

This seems to have been resolved for me in 2.5.22 but another issue has surfaced. I have updated the reproduction repo to show the new issue.

However, on 2.5.22, the bundle renderer includes 2 <link rel="stylesheet"> tags for app.css in dev builds. We're seeing this in our app locally, however we're getting 2 app.css files in both dev and production builds on 2.5.22.

I am going to upgrade the reproduction repo to the latest 2.6 release now and see if that changes anything.

@brophdawg11
Copy link
Author

Still seeing the same issue in 2.6.6 - the dev builds include two <link rel="stylesheet"> tags for app.css. See brophdawg11/vue-ssr-css-ordering@2b2acf3.

I will need to dig in further as to what's different in my app such that the bundler renderer gives us two app.css tags in both dev and prod builds.

@lyswhut
Copy link

lyswhut commented Mar 16, 2019

@brophdawg11
I also encountered the same problem, this bug has been fixed in vue-server-renderer@2.6.9
see #9677

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

No branches or pull requests

3 participants