Skip to content
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

Quasar + Nuxt3 + SSR #11165

Closed
piscis opened this issue Oct 30, 2021 · 36 comments
Closed

Quasar + Nuxt3 + SSR #11165

piscis opened this issue Oct 30, 2021 · 36 comments

Comments

@piscis
Copy link

piscis commented Oct 30, 2021

Is your feature request related to a problem? Please describe.
I would really like to integrate Quasar into Nuxt 3 with SSR mode enabled. I have a working prototype (yarn dev) that uses the Quasar Vite Plugin + Nuxt3.

The repo is here: https://github.com/piscis/nuxt-quasar-boilerplate/tree/example/quasar-vite-nuxt3-working

How every as soon as I enable SSR in nuxt.config.ts and restart vite I get the following error when my components render on the server:

window is not defined
  at $id_91abbf3f (file://./.nuxt/dist/server/server.mjs:3359:1154)  
  at async __instantiateModule__ (file://./.nuxt/dist/server/server.mjs:3812:3)

Looking at the server.mjs bundle I noticed helper referencing "window" for example:

const hasTouch="ontouchstart"in window||window.navigator.maxTouchPoints>0;

Describe the solution you'd like
I would like to enable Nuxt3 SSR mode and use Quasar Components and beeing able to render Quasar Components on the server side.

Describe alternatives you've considered

  • Using Quasar SSR Mode, but it laks the massive plugin ecosystem nuxt has like: nuxt-image, nuxt-head, nuxt-recatpcha aso. Also all of the new features like deployment to Cloudflare worker aso. Are missing with quasar SSR.
  • Keep SSR disabled not really an alternative, but more of a workaround.
  • I also tried to set:
__QUASAR_SSR__: true,
__QUASAR_SSR_SERVER__: true

But that didn't help.

Additional context
I think supporting Nuxt 3 instead of shipping a custom build SSR integration could expose Quasar Framework even more in the VUE/Nuxt ecosystem. Probably the new Nuxt CLI nuxi could help to build a wrapper around nuxt so quasar cli could provide similar support like it does today with capacitor / cap cli.

please note yarn build fails at the moment due to: nuxt/bridge#27

@piscis piscis changed the title Question: Quasar + Nuxt3 + SSR Quasar + Nuxt3 + SSR Oct 30, 2021
@JeRabix
Copy link
Contributor

JeRabix commented Oct 30, 2021

@piscis
Copy link
Author

piscis commented Oct 30, 2021

@JeRabix sorry have forgotten to make it public it should work now

@webfansplz
Copy link

@rstoenescu Same issue, do we have any plans to support Nuxt3 ? thanks

@webfansplz
Copy link

image
Looks like a limit. Is there a support plan ?

@piscis
Copy link
Author

piscis commented Nov 8, 2021

Looking at the type-definitions of the vite plugin I could find that a ssr-server and ssr-client mode could be available at some point:

Source:

/**
* How will Quasar be used? In a:
* "web-client" (default)
* "ssr-server" (NOT YET AVAILABLE) SSR on server-side
* "ssr-client" (NOT YET AVAILABLE) SSR on client-side
*/
// runMode?: "web-client" | "ssr-client" | "ssr-server";
}

But I'm confused if that means that Quasar + Vite + SSR could eventually work with SSR / SSG frameworks like nuxt?

@hawkeye64
Copy link
Member

#11231

@stefanvanherwijnen
Copy link
Contributor

I am having the same issue with quasar-app-vite and it is caused by defining quasar in noExternal, which bundles quasar.esm.prod.js which in turn is a browser build.

@piscis
Copy link
Author

piscis commented Dec 6, 2021

For anyone who is interested.

~~https://github.com/piscis/nuxt-quasar-boilerplate/tree/example/quasar-vite-nuxt3-working ~~

This branch contains a Nuxt3 + Quasar setup that produces a production build.

~~ Spoiler:~~

Screenshot 2021-12-06 at 17 09 18

There are still some limitations:

1. No real SSR support due a problem with the ssr flag set to false in nuxt-config, in order to get it to work I wrapped the root element with <client-only /> and build it with SSR enabled.
2. There is a problem mit vue vite plugin + Nuxt and the new quasar transformAssetUrls helper from quasar. I think at the moment it's not possible to use multiple vue vite plugins in nuxt and therefore using transformAssetUrls helper will break the Nuxt vite config.

But in theory its possible to get quasar working with nuxt via vite and build it.

Update: please see my comment here: #11165 (comment)

@angelhdzdev
Copy link
Contributor

I managed to get it working like this:

  1. In root folder (or if you are using srcDir in Nuxt's config it would be the src folder), create a plugins folder.
  2. Inside plugins folder, create a quasar.client.ts file.
  3. Inside quasar.client.ts, add the following code:
import { NuxtApp } from 'nuxt/dist/app/nuxt';
import {Quasar} from 'quasar';
import '@quasar/extras/roboto-font/roboto-font.css'
import '@quasar/extras/material-icons/material-icons.css'
import '@quasar/extras/fontawesome-v6/fontawesome-v6.css'

// Import Quasar css
import 'quasar/dist/quasar.css'

export default defineNuxtPlugin((nuxtApp: NuxtApp): unknown => {
  nuxtApp.vueApp.use(Quasar, {})
  return {
    
  }
})

(remember to run npm install quasar @quasar/extras)

  1. Everything will render, but a [Vue Warn] warnings come up about adding some Vue Compiler options to specify Quasar's components as custom components, so I finally solved this by setting ssr: false in Nuxt's config.

Even though I'm glad I finally can render Quasar in Nuxt 3, some questions came up:
Why can't Quasar work SSR? Why can't Quasar be smoothly installed as a Quasar Vite Plugin if Nuxt supports Vite now?

@stefanvanherwijnen
Copy link
Contributor

Quasar has its own SSR logic and functions which need to be handled appropriately. In contrast to most UI frameworks, Quasar has built in support for SSR and things are rendered differently depending on if its rendered on the server or the client:

export const isRuntimeSsrPreHydration = __QUASAR_SSR_SERVER__
? { value: true }
: ref(
__QUASAR_SSR_CLIENT__ && (
__QUASAR_SSR_PWA__ ? document.body.getAttribute('data-server-rendered') !== null : true
)
)

Quasar only officially supports using @quasar/app-vite. It is possible to use Quasar SSR with Nuxt, but Nuxt will have to add support for Quasar. It definitely is possible, but not without some workarounds.

If you want to use SSR with Quasar, use Quasar CLI.

@stefanvanherwijnen
Copy link
Contributor

Providing SSR rendered Quasar components to Nuxt seems pretty straight forward (replace the platform variables with the correct import.meta.env.SSR value and build from src), but in order to prevent hydration errors the generated HTML needs to be transformed.

If any experienced Nuxt user knows how to do this, it should be possible to have Quasar SSR support in Nuxt.

@angelhdzdev
Copy link
Contributor

Im new to Nuxt and to SSR. No idea. I just wanted to have Quasar as UI in Nuxt instead of Vuetify.

@TomMiller-mas
Copy link

For anyone who is interested.

https://github.com/piscis/nuxt-quasar-boilerplate/tree/example/quasar-vite-nuxt3-working

This branch contains a Nuxt3 + Quasar setup that produces a production build.

Not with the latest and greatest Nuxt 3 and your latest components.

,
"dependencies": {
"@quasar/extras": "^1.15.1",
"nuxt": "^3.0.0-rc.6",
"quasar": "^2.7.7"
},
"devDependencies": {
"@quasar/vite-plugin": "^1.1.1",
"sass": "1.32.0"
}

node 16.15.1

nuxt.conifg.ts => Should just be i**mport { defineNuxtConfig } from "nuxt";**

And I get these errors. Something in the syntax must have changed for registering components. I am completely new with your product and would appreciate a little help. Thanks!

[Vue warn]: Failed to resolve component: q-layout
[Vue warn]: Failed to resolve component: q-header
[Vue warn]: Failed to resolve component: q-toolbar
[Vue warn]: Failed to resolve component: q-btn
[Vue warn]: Failed to resolve component: q-toolbar-title
[Vue warn]: Failed to resolve component: q-drawer
[Vue warn]: Failed to resolve component: q-list
[Vue warn]: Failed to resolve component: q-item-label
[Vue warn]: Failed to resolve component: q-item
[Vue warn]: Failed to resolve component: q-item-section
[Vue warn]: Failed to resolve component: q-icon
[Vue warn]: Failed to resolve component: q-page-container

@TomMiller-mas
Copy link

Everything will render, but a [Vue Warn] warnings come up about adding some Vue Compiler options to specify
Quasar's components as custom components, so I finally solved this by setting ssr: false in Nuxt's config.

This solved my warning problems. It seems to be working with the original template with just two changes. Both of them are in the nuxt.config.ts.

@piscis
Copy link
Author

piscis commented Nov 12, 2022

There is an update for Nuxt3 (now rc13) and Quasar 2 here: https://github.com/piscis/nuxt-quasar-boilerplate

By using JSDOM as server plugin and mocking browser dependencies it is now possible to run a full SSR build. But for complicated layouts using q-layout there are still hydration errors probably caused by resize observer.

Demo: https://nuxt3-quasar.piscis.io/

@angelhdzdev
Copy link
Contributor

Im new to Nuxt and to SSR. No idea. I just wanted to have Quasar as UI in Nuxt instead of Vuetify.

@Jason What was funny about my message!?

image

@JasonLandbridge
Copy link

JasonLandbridge commented Dec 11, 2022

Im new to Nuxt and to SSR. No idea. I just wanted to have Quasar as UI in Nuxt instead of Vuetify.

@Jason What was funny about my message!?

image

@angelhdzmultimedia, I found it funny because I had the exact same mindset. All the other emoticons didn't accurately describe on how I felt about your comment, so I choose the laughing one.

@angelhdzdev
Copy link
Contributor

angelhdzdev commented Dec 11, 2022

Im new to Nuxt and to SSR. No idea. I just wanted to have Quasar as UI in Nuxt instead of Vuetify.

@Jason What was funny about my message!?
image

@angelhdzmultimedia, I found it funny because I had the exact same mindset. All the other emoticons didn't accurately describe on how I felt about your comment, so I choose the laughing one.

Oooh. That makes sense. My apologies for being paranoid but I've received the laughing reaction before as a way of judging my answers so I'm always in full paranoia mode, also I suffer from generalized anxiety.

So cool that other people faced the same wall I faced with Nuxt+ Quasar. Hope there's an official solution soon other than disabling SSR and making then app an SPA one.

Also, I'm considering trying Quasar CLI + Vite and its SSR.

Thank you for your time! Cheers.

@NikolaStojicic
Copy link

@angelhdzmultimedia I had similar issue and went with Quasar + Vite route.

Copied most of Vite plugins from https://github.com/antfu/vitesse to make Quasar feel more like Nuxt (auto-imports of components, pages, layouts etc).

Using it's SSR with tRPC v10 for backend.

Pretty good DX, a bit slow to start due to bloat of plugins strapped.

@buithaibinh
Copy link

By using JSDOM to mock the DOM, we can use Quasar 2 with Nuxt 3. You can refer to this article for more details.

Quasar 2 with Nuxt3

import { JSDOM } from "jsdom";

const dom = new JSDOM(
  "<!DOCTYPE html><head></head><body><h1>FAKE DOM</h1></body></html>",
  {
    url: "https://example.org/",
    referrer: "https://example.com/",
    contentType: "text/html",
    includeNodeLocations: true,
    storageQuota: 10000000,
  }
);

const { XMLHttpRequest } = dom.window;
global.XMLHttpRequest = XMLHttpRequest;
// @ts-ignore
global.window = dom.window;
global.navigator = dom.window.navigator;
global.document = dom.window.document;
// @ts-ignore
global.FileList = dom.window.FileList;
global.File = dom.window.File;
global.getComputedStyle = dom.window.getComputedStyle;

export default defineNuxtPlugin((_nuxtApp): void => {});

@NikolaStojicic
Copy link

By using JSDOM to mock the DOM, we can use Quasar 2 with Nuxt 3. You can refer to this article for more details.

Quasar 2 with Nuxt3

import { JSDOM } from "jsdom";

const dom = new JSDOM(
  "<!DOCTYPE html><head></head><body><h1>FAKE DOM</h1></body></html>",
  {
    url: "https://example.org/",
    referrer: "https://example.com/",
    contentType: "text/html",
    includeNodeLocations: true,
    storageQuota: 10000000,
  }
);

const { XMLHttpRequest } = dom.window;
global.XMLHttpRequest = XMLHttpRequest;
// @ts-ignore
global.window = dom.window;
global.navigator = dom.window.navigator;
global.document = dom.window.document;
// @ts-ignore
global.FileList = dom.window.FileList;
global.File = dom.window.File;
global.getComputedStyle = dom.window.getComputedStyle;

export default defineNuxtPlugin((_nuxtApp): void => {});

Does not this approach disable Quasar CLI?

@angelhdzdev
Copy link
Contributor

angelhdzdev commented Jan 30, 2023

@angelhdzmultimedia I had similar issue and went with Quasar + Vite route.

Copied most of Vite plugins from https://github.com/antfu/vitesse to make Quasar feel more like Nuxt (auto-imports of components, pages, layouts etc).

Using it's SSR with tRPC v10 for backend.

Pretty good DX, a bit slow to start due to bloat of plugins strapped.

Yup, same here. I went full Quasar with router/layouts/modules auto-import .
Could deploy to Android with Capacitor and Desktop with Electron.

But then I got back to Nuxt 3 to check if support for Quasar was added after Vuetify 3 was released.
And I realized I didn't need SSR so I turned SSR off and then Quasar worked as a SPA.

With Nuxt 3, we have the auto-imports already. No need to install bunch of packages.
I hope Quasar team adds a module/plugin for Nuxt 3 so we could be free to use Quasar only as an UI library and not being tied to their ecosystem and that also they add auto-imports in Quasar Vite CLI project.

@buithaibinh
Copy link

Does not this approach disable Quasar CLI?

@NikolaStojicic ,
Yes, you cannot use quasar cli and Nuxt together. Nuxt 3 also does not support the quasar.conf.js file

@angelhdzdev
Copy link
Contributor

There is an update for Nuxt3 (now rc13) and Quasar 2 here: https://github.com/piscis/nuxt-quasar-boilerplate

By using JSDOM as server plugin and mocking browser dependencies it is now possible to run a full SSR build. But for complicated layouts using q-layout there are still hydration errors probably caused by resize observer.

Demo: https://nuxt3-quasar.piscis.io/

Got it working thanks.
Though any ideas how to get rid of these Vue warnings?
image

I followed the boilerplate carefully. Nuxt config is the same. fake-dom.server.ts is the same.
quasar.client.ts is the same.

@piscis
Copy link
Author

piscis commented Feb 9, 2023

Hello everybody, I did some more work on this topic and now it seems, that fully SSR support with quasar is possible. To get SSR to work I used the happy-dom package which has a far better DOM implementation as JSDOM when using it together with Quasar and Nuxt. JSDOM is not needed anymore and the implementation for the fake-dom part are basically 3 lines of code:

https://github.com/piscis/nuxt-quasar-boilerplate/blob/main/plugins/fake-dom.server.ts

A boilerplate with the full source code can be found here: https://github.com/piscis/nuxt-quasar-boilerplate/ and the demo is here: https://github.com/piscis/nuxt-quasar-boilerplate

@piscis
Copy link
Author

piscis commented Feb 9, 2023

Also please note what gets promoted here #11165 (comment) a old implementation with JSDOM. This is problematic when it comes to SSR and Quasar because some APIs quasar needs are not provided via JSDOM and lead to rehydration errors with q-layout / q-page when used with Nuxt3 + SSR

@xuzuodong
Copy link
Contributor

@piscis What you've done is quite nice, do you think it's possible to go further and make it a nuxt module, just like element-plus?

@piscis
Copy link
Author

piscis commented Feb 13, 2023

@xuzuodong yes that is possible I guess. The biggest problem with the current implementation is that you need to wire everything by hand in a plugin. If this is covered via a module, we would need some sort of component configuration. I already toke some inspiration from https://github.com/sfxcode/nuxt-primevue to see how they solve it for primevue

@rstoenescu
Copy link
Member

Closing this as using our CLI(s) to develop SSR is the official way to go, at least for now. And this ticket is confusing some developers into thinking that Quasar does not supports SSR, which couldn't be more WRONG.

Our Vite plugin supports SSR through its params (configures all the __QUASAR__* aliases for both client and server), but it may or may not not be enough when it comes to Nuxt. Currently, we don't have time to fully investigate or create a Nuxt plugin due to the heavy load with our current tooling. This may however change in the future and we will make sure to announce it, but Nuxt is not currently on our radar because through our CLIs we have greater control over the SSR experience and we can make it be as efficient as possible.

Everyone please feel free to still comment on this thread with your findings, but again, take into account that our Vite plugin has specific params for SSR. https://github.com/quasarframework/quasar/blob/dev/vite-plugin/index.d.ts#L32

@angelhdzdev
Copy link
Contributor

Closing this as using our CLI(s) to develop SSR is the official way to go, at least for now. And this ticket is confusing some developers into thinking that Quasar does not supports SSR, which couldn't be more WRONG.

Our Vite plugin supports SSR through its params (configures all the __QUASAR__* aliases for both client and server), but it may or may not not be enough when it comes to Nuxt. Currently, we don't have time to fully investigate or create a Nuxt plugin due to the heavy load with our current tooling. This may however change in the future and we will make sure to announce it, but Nuxt is not currently on our radar because through our CLIs we have greater control over the SSR experience and we can make it be as efficient as possible.

Everyone please feel free to still comment on this thread with your findings, but again, take into account that our Vite plugin has specific params for SSR. https://github.com/quasarframework/quasar/blob/dev/vite-plugin/index.d.ts#L32

Thank you! I have a question:
Does quasar in SSR mode, have layouts, routes/pages, and modules auto-imports, or do we still have to rely in packages like unplugin-vue-router, unplugin-auto-import, and vite-plugin-vue-layouts to achieve it?

That's the reason I've been working with Nuxt 3 lately instead of Quasar with Vite.

@Maiquu
Copy link

Maiquu commented Mar 7, 2023

Using @quasar/vite-plugin as a reference, and a bit of inspiration from @element-plus/nuxt, I implemented a Quasar Module for Nuxt. Feedback would be very appreciated.

Do keep in mind that there are hydration issues with some of the Quasar components at the moment. (q-drawer in particular)

@angelhdzdev
Copy link
Contributor

Using @quasar/vite-plugin as a reference, and a bit of inspiration from @element-plus/nuxt, I implemented a Quasar Module for Nuxt. Feedback would be very appreciated.

Do keep in mind that there are hydration issues with some of the Quasar components at the moment. (q-drawer in particular)

Will try it tonight, thanks!

@angelhdzdev
Copy link
Contributor

Using @quasar/vite-plugin as a reference, and a bit of inspiration from @element-plus/nuxt, I implemented a Quasar Module for Nuxt. Feedback would be very appreciated.

Do keep in mind that there are hydration issues with some of the Quasar components at the moment. (q-drawer in particular)

Tried it. It works great. Looked at the source code.

Are you using jsdom or @happy-dom/global-registrator to avoid the "undefined property window" errors? Or did you found another way?

@Maiquu
Copy link

Maiquu commented Mar 10, 2023

Are you using jsdom or @happy-dom/global-registrator to avoid the "undefined property window" errors? Or did you found another way?

Window errors are due to @quasar/vite-plugin resolving quasar imports to quasar/dist/quasar.esm.js file which is most likely bundled for clients.

Instead of resolving imports to quasar/dist files, I resolve each import directly to their quasar/src equivalents which contains the necessary flags to compile them for both server and client. It results in more file read operations but performance difference is not very noticeable.

@angelhdzdev
Copy link
Contributor

Using @quasar/vite-plugin as a reference, and a bit of inspiration from @element-plus/nuxt, I implemented a Quasar Module for Nuxt. Feedback would be very appreciated.

Do keep in mind that there are hydration issues with some of the Quasar components at the moment. (q-drawer in particular)

Hey @piscis, not intend to bother you. Just wanted you to noticed this solution and know your thoughts.
To me it looks great so far and the fact that it's a nuxt module, that does the heavy load for us, it's even better!
Maybe you can benefit from it.

Wishing you all health, peace, and success!

Have fun! 😊🔥🤝☕

@septatrix
Copy link

Using @quasar/vite-plugin as a reference, and a bit of inspiration from @element-plus/nuxt, I implemented a Quasar Module for Nuxt. Feedback would be very appreciated.

I will try this out for a new project I am currently working on, at a first glance (2h playing around) it seems to work fine.

Do keep in mind that there are hydration issues with some of the Quasar components at the moment. (q-drawer in particular)

I did not stumble upon this yet, though if it becomes to troublesome I am luckily in the position where I could also live without SSR. I am mostly using Quasar for the great components.

Does quasar in SSR mode, have layouts, routes/pages, and modules auto-imports, or do we still have to rely in packages like unplugin-vue-router, unplugin-auto-import, and vite-plugin-vue-layouts to achieve it?

This is also our main motivation for Nuxt. We mostly use Quasar as a component library and Nuxt for the file based routing, (typed) API routes, but also some other neat modules (though some of those have yet to be ported to Nuxt 3).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests