0

According to the docs:

https://quasar.dev/quasar-cli/developing-ssr/writing-universal-code#Component-Lifecycle-Hooks

Since there are no dynamic updates, of all the Vue lifecycle hooks, only beforeCreate and created will be called during SSR. This means any code inside other lifecycle hooks such as beforeMount or mounted will only be executed on the client.

I'm confused at how to make this call happen. I have some stuff that can't run on the server. I would have guessed that having "mounted" alone would cause it to fire, but that doesn't seem to happen.

To add a little context, I'm building a drop-down menu using foundation. I have it working on standard Vue (non-ssr).

The file looks like this:

<template>

<ul class="vertical menu accordion-menu" data-accordion-menu data-multi-open="false">
    <li v-for="i in htmlData.sidenav" :key="i.title">
        <router-link v-bind:to=i.href>{{ i.title }}</router-link>
        <ul class="menu vertical nested" v-if="i.sub1">
            <li v-for="j in i.sub1" :key="j.name">
                <router-link v-bind:to=j.href>{{ j.name }}</router-link>
                <ul class="menu vertical nested" v-if="j.sub2">
                    <li v-for="k in j.sub2" :key="k.name">
                        <router-link v-bind:to=k.href>{{ k.name }}</router-link>
                      </li>
                  </ul>
              </li>
          </ul>
      </li>
  </ul>
</div>


</template>


<script>
import SideNav from '../store/modules/sidenav'
import $ from 'jquery'

export default {
    name: 'sidenav',

    computed: {
        htmlData () {
            this.acc()
            return this.$store.state.sn.nav
        }
    },

    // Server-side only
    serverPrefetch () {
        this.$store.registerModule('sn',  SideNav)
        return this.getData()
    },

    // Client-side only
    mounted () {
        console.log('mt')
        const doesExist = !!this.$store.state.sn.nav
        this.$store.registerModule('sn', SideNav, { preserveState: true })

        if (!doesExist) {
            this.getData()
        }
    },

    destroyed () {
        this.$store.unregisterModule('sn')
        this.menu.destroy()
    },

    methods: {
        async getData () {
            return this.$store.dispatch('sn/snav')
        },

        acc () {
            this.$nextTick(function () {
                this.menu = new this.$foundation.AccordionMenu($('.accordion-menu'))
            })
        },
    }
}

While the sidenav does render, the client is unable to see it, which results in this error:

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'AccordionMenu' of undefined

This is wrong because the menu does render, there is no log of mt in console, although pref does log. This causes a slew of other problems with page rendering (it doesn't without hard refresh).

The file under boot/sidenav looks like this:

// const SideNav = () => import('../layouts/SideNav.vue')
import SideNav from '../layouts/SideNav.vue'

export default async ({ Vue }) => {
    Vue.component('side-nav', SideNav)
}

And the quasar.conf has this:

        boot: [
            'axios',
            'sidenav',
            'notemenu',
            {
                path: 'foundation',
                server: false
            },
            {
                path: 'osmd',
                server: false
            }
        ],

The client can't see either foundation or osmd. Neither can run on the server since they both require window to run. It's doubly confusing because sidenav does render and behave like a reactive component.

1 Answer 1

1

Only beforeCreate and create are called in SSR and client-side. Use this component to see the lifecycle in action.

<template>
<div>Hello World</div>
</template>

<script>
export default {
name: "Test",
beforeCreate() {
 console.log('beforeCreate', process.env, this)
},
created() {
 console.log('created', process.env, this)
},
beforeMount() {
 console.log('created', process.env, this)
},
mounted() {
 console.log('mounted', process.env, this)
},
beforeUpdate() {
 console.log('beforeUpdate', process.env, this)
},
updated() {
 console.log('updated', process.env, this)
},
beforeDestroy() {
 console.log('beforeDestroy', process.env, this)
},
destroyed() {
 console.log('destroyed', process.env, this)
},
preFetch() {
 console.log('preFetch', process.env, this)
}
}
</script>

Sign up to request clarification or add additional context in comments.

3 Comments

I gave up on it. In theory, Quasar is supposed to run SSR and F/E at the same time, but it doesn't work as advertised.
Quasar extends the Vue SSR. The code is rendered on the server then passed to the browser. From the Vue SSR docs, Data Reactivity on the Server In a client-only app, every user will be using a fresh instance of the app in their browser. For server-side rendering we want the same: each request should have a fresh, isolated app instance so that there is no cross-request state pollution.
The quote in the question is from Quasar docs, and yeah, I read through and worked through the Vue SSR docs (which are only 70% correct). I worked on SSR for 3 weeks before calling it quits.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.