Replies: 3 comments
|
Collect CSS from the client build manifest, not from the SSR Rollup output.
Leave |
|
One extra detail in your config is the A typical SSR setup uses separate client and server builds. Enable |
|
I would avoid generating the stylesheet from the SSR build and hardcoding The SSR build's job is to produce the server-renderable JS. The browser should use the CSS generated by the client build, because that's the graph that corresponds to the code actually running in the browser. A typical setup is: // client vite config
export default defineConfig({
build: {
manifest: true,
cssCodeSplit: true,
},
})Then your production build produces something like: {
"src/entry-client.tsx": {
"file": "assets/entry-client-ABC123.js",
"isEntry": true,
"css": [
"assets/entry-client-XYZ789.css"
],
"imports": [
"_shared-DEF456.js"
]
},
"_shared-DEF456.js": {
"file": "assets/shared-DEF456.js",
"css": [
"assets/shared-GHI789.css"
]
}
}During SSR, read the client's
Then render: {cssFiles.map((file) => (
<link
key={file}
rel="stylesheet"
href={`/static/${file}`}
/>
))}This is important because CSS can belong to an imported/shared chunk, not just the entry itself. Vite's backend integration documentation describes this recursive I would also remove: cssCodeSplit: falsefrom the client build. Vite's default is And definitely remove: assetFileNames: "[name][extname]"for the production client build. That overrides the normal hashed asset naming, which defeats the main benefit of content-hashed assets. You can keep the SSR build separate, for example: // client
{
build: {
outDir: "dist/client",
manifest: true,
cssCodeSplit: true,
}
}
// server
{
build: {
outDir: "dist/server",
ssr: true,
},
}Then: For development, you don't need to reproduce this manifest logic. Let Vite's dev server handle CSS/HMR through its middleware. So the important distinction is: SSR build → server JS Client build → browser JS + CSS + manifest This also keeps your CSS Modules working normally: import styles from "./root.module.scss";
<Link className={styles.menuItem}>
Home
</Link>The generated CSS-module class names and the actual stylesheet both come from the client build, while the SSR build uses the module mapping needed to render the correct class name. Vite's SSR documentation also recommends separate client and SSR builds for production, with the client build providing the browser assets. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Currently we are bundling the modules into one stylesheet and hardwire its URL in the HTML outputs, which feels a bit hacky as the emits would not be hashed. Would would be the standard/proper approach?
All reactions