vite icon indicating copy to clipboard operation
vite copied to clipboard

Vite Dev Mode not loading css in react SSR application

Open chin2km opened this issue 10 months ago • 7 comments

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:

  • inlined in the html or
  • is written to the build folder so that its at least possible to inline that css file in the react ssr handler with some custom logic.

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

chin2km avatar Apr 24 '24 00:04 chin2km

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.

hi-ogawa avatar Apr 24 '24 02:04 hi-ogawa

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?

chin2km avatar Apr 24 '24 08:04 chin2km

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..).

hi-ogawa avatar Apr 24 '24 08:04 hi-ogawa

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

FreeJ1nG avatar Apr 27 '24 07:04 FreeJ1nG

@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.

natew avatar Apr 27 '24 08:04 natew

@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 :)

FreeJ1nG avatar Apr 27 '24 10:04 FreeJ1nG

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

hi-ogawa avatar Apr 28 '24 06:04 hi-ogawa