vitejs / vite

Next generation frontend tooling. It's fast!
http://vite.dev
MIT License
68.99k stars 6.24k forks source link

Vite Dev Mode not loading css in react SSR application #16515

Open chin2km opened 7 months ago

chin2km commented 7 months ago

Describe the bug

Dev mode in a react server-rendered application, the initial critical css is not inlined into the html. Styles kicks in only after the react hydration and the vite runtime loaded.

This results in a very bad flickering, especially in big applications since it takes a few seconds before the vite fetches all the required js and is browser ready.

Screenshot 2024-04-24 at 2 16 23 AM

Expectation

The stylesheet with critical css is either:

Reproduction

https://github.com/chin2km/vite-react-ssr-dev-mode-critical-css-issue

Steps to reproduce

yarn dev

and see the flickering from the server rendered page goes from a no-styles state to when the styles are loaded.

System Info

System:
    OS: macOS 14.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 1.72 GB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.0.0 - ~/.nodenv/versions/20.0.0/bin/node
    Yarn: 1.22.22 - ~/.nodenv/versions/20.0.0/bin/yarn
    npm: 7.24.2 - ~/Documents/AboutYou/tadarida-frontend-web/node_modules/.bin/npm
    pnpm: 8.15.6 - ~/.nodenv/versions/20.0.0/bin/pnpm
    bun: 0.1.10 - ~/.bun/bin/bun
  Browsers:
    Chrome: 124.0.6367.62
    Safari: 17.1

Used Package Manager

yarn

Logs

No response

Validations

hi-ogawa commented 7 months ago

At the moment Vite SSR doesn't handle this out-of-the-box and each framework has been dealing with this on their own. There are a few links in this comment https://github.com/vitejs/vite/pull/16018#issuecomment-2006385354 and you can see how frameworks implement this.

chin2km commented 7 months ago

At the moment Vite SSR doesn't handle this out-of-the-box and each framework has been dealing with this on their own. There are a few links in this comment #16018 (comment) and you can see how frameworks implement this.

Thanks for the reply! Does this mean this would be working out-of-the-box in a future Vite release?

hi-ogawa commented 7 months ago

Does this mean this would be working out-of-the-box in a future Vite release?

Hmm, I don't know about Vite team's plan. The comment I linked is just something came up when discussing about future css module change and it's not about the general FOUC issue.

From my understanding, I'm not sure if it's ideal or possible for Vite to provide something uniform to SSR users/frameworks since frameworks normally wish to manage when/how to inject CSS on their own (e.g. code splitting with file-system routing etc..).

FreeJ1nG commented 7 months ago

What i did to solve it was to create a <link /> that references the CSS files directly in index.html , this helps with the initial HTML response from the server to have the CSS content, see my repo here

natew commented 7 months ago

@FreeJ1nG that works if you only have one static file, but in the case where the page you render has css imports throughout the tree, there needs to be a way to query or intercept the imports during ssr so that you can gather them there.

FreeJ1nG commented 7 months ago

@FreeJ1nG that works if you only have one static file, but in the case where the page you render has css imports throughout the tree, there needs to be a way to query or intercept the imports during ssr so that you can gather them there.

ah I've been thinking about how such code could fail, and yea, that makes sense :)

hi-ogawa commented 7 months ago

This is not a complete solution for dev SSR FOUC issue, but just to share one approach I've been using, I extracted it to an independent plugin. https://github.com/hi-ogawa/vite-plugins/tree/main/packages/ssr-css

To adapt it to your usage, it might be easier to just copy these style collection utilities https://github.com/hi-ogawa/vite-plugins/blob/main/packages/ssr-css/src/collect.ts and directly use it for your SSR handler pipeline. (essentially that's what I've been doing by copying similar code from other frameworks as you can see from my comments there.)

@FreeJ1nG's example is a single client entry/route, so this plugin might be good enough to fix FOUC without manually managing <link>. Here is an updated example: https://stackblitz.com/edit/github-eq3fkw?file=vite.config.ts