vikejs / vike-vue

🔨 Vue integration for Vike
https://vike.dev/vike-vue
MIT License
38 stars 6 forks source link

CSS-in-JS with SSR #141

Closed mufasa71 closed 1 month ago

mufasa71 commented 3 months ago

Unable to extract CSS and put it into tag. For example:

import { createSSRApp } from 'vue'
import { renderToString } from '@vue/server-renderer'
import { setup } = from '@css-render/vue3-ssr'

// For each request, you need to create a new app
const ssrApp = createSSRApp(App)
const { collect } = setup(ssrApp)

renderToString(ssrApp).then(appHtml => {
  const css = collect()
  const page = `<!DOCTYPE html>
  <html>
    <head>${css}</head>
    <body><div id="app">${appHtml}</div></body>
  </html>`
})

as you see here we can extract CSS and render as part of HTML template.

I didn't found a way how to do it properly. Probably a new functionality should be added

brillout commented 3 months ago

It's indeed a current limitation.

The plan is to eventually have this:

// /pages/+onBeforeRenderHtml.js

import { setup } from '@css-render/vue3-ssr'

export default pageContext => {
  pageContext.collect = setup(pageContext.app)
}
// /pages/+onAfterRenderHtml.js

import { useConfig } from 'vike-vue/useConfig'

export default pageContext => {
  const config = useConfig()
  const css = pageContext.collect()
  config({ head: { dangerouslyInject: css } })
}

It's considered highest-priority so you can expect it to land sooner rather than later.

pool611 commented 2 months ago

when I use vike-react, there is no onAfterRenderHtml hook😥

brillout commented 2 months ago

@pool611 FYI creating these hooks is the easy part. The tricky part is useConfig() (there is already a rough implement but it needs polishing). I'll tentatively try to get something released this week.

brillout commented 2 months ago

The useConfig() hook is done for React: https://github.com/vikejs/vike-react/pull/128 which I'll merge after I finish writing the docs for it. Porting it to vike-vue should be relatively straightforward.

brillout commented 1 month ago

Done.

https://vike.dev/onBeforeRenderHtml https://vike.dev/onAfterRenderHtml https://vike.dev/useConfig

Pre-released as 0.8.1-commit-4184bec.

brillout commented 1 month ago

Definitely let us know if you hit any issues about the head management improvements. We're looking for feedback; there is room for improvement which we will be implementing upon user feedback.

lewis-fidlers commented 1 month ago

Hi, i know it's not exactly the correct spot to post this question, but this seems like exactly what I'm trying to do. Pretty new to the whole ssr thing.

We currently have vike setup with vike-react. And are using ant.design for our ui stuff. (we're moving from a very old stack to vike)

As per their guide, i should be able to extract the css and inject it into the page. https://ant-design.github.io/antd-style/guide/ssr

Similar to what you wrote above the hooks are however not available in vike-react, just vike-vue if I'm correct? Is there another approach needed? Or am i missing something here?

Cheers, Lewis

mufasa71 commented 1 month ago

@brillout unfortunately its not working as expected.

  1. onBeforeRenderHtml has no vue app instance, its impossible to collect styles
  2. onAfterRenderHtml impossible to call useConfig setPageContext() not called

seems like its not simple changes, but i think app should be created on very first step and passed down to context, then we can use onBeforeRenderHtml only and it should solve the issue

brillout commented 1 month ago

@mufasa71 That should be fixable. Let me circle back on this at the beginning of next week.

brillout commented 1 month ago

@mufasa71 That should be fixable. Let me circle back on this at the beginning of next week.

Done:

Pre-released in 0.8.2-commit-6c63604.

Let me know how it goes. If you want, you can provide a reproduction so that I can directly test changes against it and make the integration work.

lewis-fidlers commented 1 month ago

@pool611 I believe this might be of help to you as well: https://github.com/vikejs/vike/discussions/1804

mufasa71 commented 1 month ago

@brillout https://codesandbox.io/p/devbox/zealous-julien-m98tkw Created minimal sandbox. Still unable to extract styles.

brillout commented 1 month ago

@mufasa71 Can you publish it on Github?

Jearce commented 1 month ago

@brillout I have a minimal working example here: https://github.com/Jearce/vike-vue-naive-ui. Seems fine to me.

phonzammi commented 1 month ago

The result of const css = collect() is a string, which I don't think works if passed to config({ Head: css })."

pdanpdan commented 1 month ago

Check the example just above

phonzammi commented 1 month ago

@Jearce, I'm sorry, but I think there’s a typo: config({ head: should be config({ Head: with a capital H.

Jearce commented 1 month ago

Thanks, I see what you mean. The example I shared above is a false positive even fixing the typo. I was able to confirm with the following command: curl -s http://localhost:3000/ | awk '/<\<head>/,/<\/head>/ {print}'

The head HTML, server-side, is not being rendered with the CSS. I think the getHeadHtml function would need to be updated to consider injecting raw CSS/style string in head.

brillout commented 1 month ago

I think the getHeadHtml function would need to be updated to consider injecting raw CSS/style string in head.

I think doing something similar to what we're doing in the example below works?

config({
  Head: h('script', {
    type: 'application/ld+json',
    innerHTML: JSON.stringify({
      '@context': 'https://schema.org/',
      contentUrl: { src },
      creator: {
        '@type': 'Person',
        name: author,
      },
    }),
  }),
})
Jearce commented 1 month ago

Yes, that works:

 config({ 
    Head: h('style', {
      innerHTML: css
    })
  })

I updated the example I shared above and the styles are now correctly rendered server-side.

brillout commented 1 month ago

@Jearce Thank you! I've added your example to the docs https://vike.dev/naive-ui. Also, a Vike extension vike-vue-naive-ui would be neat in case that's something you'd be up for. You can have a look at https://github.com/vikejs/vike-vue/tree/main/packages/vike-vue-pinia and https://github.com/vikejs/vike-vue/tree/main/packages/vike-vue-query — it's relatively simple.

@mufasa71 If you're up for it, you can publish a working example, and I'll link to it from the docs.

I guess we can close this. Let us know if you run into any unresolved issues.

phonzammi commented 1 month ago
 config({ 
    Head: h('style', {
      innerHTML: css
    })
  })

I'm sorry, but I don’t think it’ll work. The css already includes multiple <style> tags, and when I tried it, I saw a FOUC (or a flash with different style to be precise) for a second. But we can use a custom tag like this :

config({
    Head: h("css-style", {
      innerHTML: css,
    }),
  });
brillout commented 1 month ago

@phonzammi :+1: Or using a fragment instead of css-style would work as well I guess. I can't speak for Jearce but I guess PR welcome to https://github.com/Jearce/vike-vue-naive-ui.

brillout commented 1 month ago

Improved the docs https://vike.dev/Head and added How to inject raw HTML?.

Jearce commented 4 weeks ago

@phonzammi Thanks! The issue should be fixed now. @brillout Yes, I am down. I'll make a PR for the Vike extension when ready.

brillout commented 4 weeks ago

Neat :100:. If you want, we can host the extension under your name at https://github.com/Jearce/vike-vue-naive-ui (I guess we can move the example to another URL like https://github.com/Jearce/vike-naive-ui). I went ahead and grabbed https://www.npmjs.com/package/vike-vue-naive-ui — let me know what your npm handle and I'll make you co-admin.

Jearce commented 3 weeks ago

@brillout My npm handle is jearce and https://github.com/Jearce/vike-vue-naive-ui should be a valid vike extension now. I will add an example later this week.

brillout commented 3 weeks ago

Awesome :100: Updated docs: https://vike.dev/naive-ui. (As for the exmple @todo I recommend a pnpm monorepo with at the root: example/ and packages/vike-vue-naive-ui/ or vike-vue-naive-ui/.)

mufasa71 commented 3 weeks ago

@brillout @Jearce just checked and everything works fine now. Great Job! Looking forward to the naive extension, so far the package seems broken :)

Jearce commented 3 weeks ago

@brillout Done. The git repo https://github.com/Jearce/vike-vue-naive-ui is now a pnpm monorepo and should be ready to publish to npm. I don't have perm to publish myself. The package should work although I only tested it on a local Verdaccio instance.

brillout commented 2 weeks ago

@Jearce :100: Let me know your npm handle and I'll make you co-admin.

Jearce commented 2 weeks ago

npm handle: https://www.npmjs.com/~jearce

brillout commented 2 weeks ago

Done.

$ npm owner add jearce vike-vue-naive-ui
+ jearce (vike-vue-naive-ui)