-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
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
SSR HTML transformation in middleware mode doesn't add style tags for statically imported css #2013
Comments
That's expected, imported CSS are dynamically injected at runtime during dev. |
Just to clarify, is it possible to fix the flash of unstyled content and it’s just deemed to be too much work, or is there some fundamental limitation that makes dev work differently than the build such that it can’t really be fixed? |
And, could we add an API so dev time integrations could serve the linked assets from a module within SSR’d HTML if they wanted to? |
Curious about this as well. |
@airhorns See the #ssr channel discussion https://discord.com/channels/804011606160703521/804061937029218334/814909610372366346 |
Got a userland patch done quickly with the guidance from @brillout linked discussion. Don't think I will spend time on more polished version for internals right now but maybe this can help someone in the meantime. /* relevant snippet from server.js */
const cssUrls = [], cssJsUrls = []
function collectCssUrls(mod) {
mod.importedModules.forEach(submod => {
if (submod.id.match(/\?vue.*&lang\.css/)) return cssJsUrls.push(submod.url)
if (submod.file.endsWith(".css")) return cssUrls.push(submod.url)
if (submod.file.endsWith(".vue")) return collectCssUrls(submod)
// XXX need to continue recursing in your routes file
if (submod.file.match(/route/)) return collectCssUrls(submod)
})
}
let render
if (!isProd) {
render = (await vite.ssrLoadModule("/src/entry-server.js")).render
const mod = await vite.moduleGraph.getModuleByUrl('/src/app.js') /* replace with your entry */
cssUrls = mod.ssrTransformResult.deps.filter(d => d.endsWith(".css"))
} else {
render = require("./dist/server/entry-server.js").render
}
const [appHtml] = await render(url, manifest)
const devCss = cssUrls.map(url => {
return `<link rel="stylesheet" type="text/css" href="${url}">`
}).join("") + cssJsUrls.map(url => {
return `<script type="module" src="${url}"></script>`
}).join("")
const html = template.replace(`<!--app-html-->`, appHtml).replace(`<!--dev-css-->`, devCss) Older version missing the SFC style blocks: /* relevant snippet from server.js */
let cssUrls = []
let render
if (!isProd) {
render = (await vite.ssrLoadModule("/src/entry-server.js")).render
const mod = await vite.moduleGraph.getModuleByUrl('/src/app.js') /* replace with your entry */
cssUrls = mod.ssrTransformResult.deps.filter(d => d.endsWith(".css"))
} else {
render = require("./dist/server/entry-server.js").render
}
const [appHtml] = await render(url, manifest)
const css = cssUrls.map(url => `<link rel="stylesheet" type="text/css" href="${url}">`).join("")
const html = template.replace(`<!--app-html-->`, appHtml).replace(`<!--dev-css-->`, css) |
Vue tracks the loaded CSS in the context object, see the |
The You are talking about here? https://github.com/vitejs/vite/blob/main/packages/playground/ssr-vue/src/entry-server.js#L16 |
PS: My updated comment above now includes the SFC style blocks. Probably very suboptimal but looks like it works decently for dev for now. |
@tjk Yes I exactly meant that |
Describe the bug
During development, when using vite in middleware mode like the
ssr-react
example, CSS source files imported by the entrypoint aren't sourced via a<link/>
tag in the transformed HTML. This results in a flash of unstyled content because the server rendered response doesn't include the CSS, but during hydration, the client renders and imports the style.I believe that in normal, vite is the server serving the HTML mode, these static imports get parsed out and written into the HTML file served to the user.
Reproduction
You can try out the branch at main...airhorns:ssr-static-assets, which just adds a static import for a CSS file to the
App.tsx
entrypoint in thessr-react
playground.The server rendered HTML:
The DOM tree after rendering client side:
Note the added inline script tag with the
background-color: red;
It'd be great for vite to support this same transform when doing
transformIndexHtml
, but also, if there was a way to get the list of imports necessary for sticking into the HTML when doingssrLoadModule
, that'd be awesome too! If you build you can usemanifest: true
orssrManifest: true
to get enough information out of vite to create the right HTML file, but, that's only after building, so if we wanted to support people doing this during development, it'd be great to have an API for getting the list of static imports that anssrLoadModule
should demand.Thanks for an awesome piece of software!
System Info
vite
version: 2a6109aDarwin inspector 20.2.0 Darwin Kernel Version 20.2.0: Wed Dec 2 20:39:59 PST 2020; root:xnu-7195.60.75~1/RELEASE_X86_64 x86_64
v15.7.0
yarn 1.22.10
The text was updated successfully, but these errors were encountered: