Screen Plugin in SSR mode is defaulting mobile sizes
See original GitHub issueDescribe the bug When SSR prerendering a view on desktop,a mobile screen is assumed causing a blink that can be very confusing when developing a responsive site (for example, using the grid view for mobile and normal view in desktop for a QTable, as shown in screenshot)
Expected behavior The Screen plugin should detect the platform (it can do that via request headers analyzing) and use a better heuristic to determine which size we have. I’v checked out the code and its doing this:
if (isSSR === true) {
$q.screen = this
return
}
(Making $q.screen = this defaults to mobile sizes)
Screenshots
Responsive table rendered as mobile on server and rendering as desktop on client side. Also the left drawer disappears server side and appears back on client

Platform (please complete the following information):
Operating System - Linux(4.19.69-1-MANJARO) - linux/x64 NodeJs - 12.9.1
Global packages NPM - 6.11.2 yarn - 1.17.3 @quasar/cli - 1.0.0 cordova - Not installed
Important local packages quasar - 1.1.0 – Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time @quasar/app - 1.0.6 – Quasar Framework local CLI @quasar/extras - 1.3.1 – Quasar Framework fonts, icons and animations vue - 2.6.10 – Reactive, component-oriented view layer for modern web interfaces. vue-router - 3.1.2 – Official router for Vue.js 2 vuex - 3.1.1 – state management for Vue.js electron - Not installed electron-packager - Not installed electron-builder - Not installed @babel/core - 7.5.5 – Babel compiler core. webpack - 4.39.3 – Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, … and your custom stuff. webpack-dev-server - 3.8.0 – Serves a webpack app. Updates the browser on changes. workbox-webpack-plugin - 4.3.1 – A plugin for your Webpack build process, helping you generate a manifest of local files that workbox-sw should precache. register-service-worker - 1.6.2 – Script for registering service worker, with hooks
Quasar App Extensions None installed
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:10 (5 by maintainers)

Top Related StackOverflow Question
@jigarzon
Coming back to this. This would be a start, however there’s a major issue which I will detail at the end of the post.
The issue is that Screen is a singleton. Meaning you can’t just change its properties. Serving multiple SSR clients at the same time will render a non deterministic output, since there’s lots of async “gateways” in the code. One client might start being served while another changes the Screen singleton and it will end with rendered output with some content with the old values from Screen and the rest with the new changed values.
Furthermore, even if we go over this problem, then comes another one. Better Screen assumptions won’t mean that Layout components (header/footer/drawer/page/page-sticky/…) can be rendered on SSR as on a SPA, because they need to communicate with each other (for sizes, offsets, etc). So for SSR, it would matter a lot the order in which template declares those components. If a QHeader is before the QPage, then QPage would have the correct size, but not if QPage is declared before QHeader. On server-side we have: render QLayout --> hey, we have a QPage here, so render QPage --> ok, here is QPage, going back to QLayout render --> hey, we have a QDrawer, so render QDrawer --> …and so on. So rendering a subcomponent is “final” and if a subsequent component communicates with the layout, the first subcomponent is NOT getting these updates.
But let’s assume we get over this problem too. QDrawer does not uses a Vue state to render the left/right position because this would mean opening/closing by touch/mouse dragging requires a Vue rerender. And you need LOTS of re-renders while you swipe – this would make QDrawer act far far away from smooth (it would be ridiculously slow!). So to avoid this, QDrawer acts upon the DOM node directly (only for updating this part of the position). On SSR, again, you cannot do this (access DOM, cause there’s no DOM), so the initial state (even if it was decided that “hey, we’ll have it on layout”) cannot be applied (it will still be hidden until we takeover from client-side).
I’d continue, but it’s already a very long post (sorry) 😃
Thanks Razvan for such a big explanation. This is exactly what I wanted. I don’t understand reason #2, maybe I’m missing something, but what would be the problem if everyone ask size and it’s 1920x1080? Despite of declaration order? I understand that Layout components need to communicate and are dependant, but right now they can perfectly overcome the situation of a changing size viewport (when I manually resize screen size on browser). Sorry but maybe I’m losing the architecture of those. But I don’t understand why assuming an initial size would cause problems. The #3 situation regarding DOM can be the most challenging, but let me ask you: isn’t the biggest work for making it work on ssr already done? I mean: right now it comes correctly rendered on ssr on the correct side, and it disappears on the client side. So , have you tested that code and it’s breaking? Thanks a lot for going so deep in this, I really appreciate it. I think this is limiting a true implementation of the “code once use everywhere”. A ui designer reported that on a normal connection he had to wait almost 7 seconds with the screen broken because of this reason, and I could reproduce. Let me start working further with this next week, sorry last week I had no time.
El sáb., 21 sept. 2019 6:30, Razvan Stoenescu notifications@github.com escribió: