quasar
quasar copied to clipboard
Quasar + Nuxt3 + SSR
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 link "The repo is here: https://github.com/piscis/nuxt-quasar-boilerplate/tree/example/quasar-vite-nuxt3-working" not work :(
@JeRabix sorry have forgotten to make it public it should work now
@rstoenescu Same issue, do we have any plans to support Nuxt3 ? thanks
Looks like a limit. Is there a support plan ?
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: https://github.com/quasarframework/quasar/blob/3311a20827c4858e2a9f794ad262308b5068eac1/vite-plugin/index.d.ts#L24-L31
But I'm confused if that means that Quasar + Vite + SSR could eventually work with SSR / SSG frameworks like nuxt?
https://github.com/quasarframework/quasar/issues/11231
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.
~~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:
~~~~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: https://github.com/quasarframework/quasar/issues/11165#issuecomment-1312528612
I managed to get it working like this:
- In root folder (or if you are using srcDir in Nuxt's config it would be the src folder), create a plugins folder.
- Inside plugins folder, create a quasar.client.ts file.
- 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
)
- 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?
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: https://github.com/quasarframework/quasar/blob/ac8441d83dd8b2f71e80ef69c27681d8b8a2a51b/ui/src/plugins/Platform.js#L14-L20
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.
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.
Im new to Nuxt and to SSR. No idea. I just wanted to have Quasar as UI in Nuxt instead of Vuetify.
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
Yes sorry it turns out using quasar + vite + nuxt is a bit more challenging, and I decided to abandone Quasar as UI only solution and use something else. Also updated the comment so it's not misleading for other people looking for a solution.
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.
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/
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!?
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!?
@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.
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!?
@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.
@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.
By using JSDOM to mock the DOM, we can use Quasar 2 with Nuxt 3. You can refer to this article for more details.
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 => {});
By using JSDOM to mock the DOM, we can use Quasar 2 with Nuxt 3. You can refer to this article for more details.
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?
@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.
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
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?
I followed the boilerplate carefully. Nuxt config is the same. fake-dom.server.ts is the same. quasar.client.ts is the same.
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
Also please note what gets promoted here https://github.com/quasarframework/quasar/issues/11165#issuecomment-1407905736 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
@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?
@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
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
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.