Subscribe on changes!

Watch (flush: 'sync') (which is not bound to component live cycle) is not respected in server renderer.

avatar
May 26th 2022

Vue version

3.2.36

Link to minimal reproduction

https://codesandbox.io/s/vue-ssr-watch-sync-bug-xr5jql?file=/src/App.vue:115-356

Steps to reproduce

Make setup function does things as such

<template>
  <div>{{test2}}</div>
</template>
<script>
import {ref, watch} from 'vue'
export default {
  setup() {
    const testRef = ref(0)
    let test2 = 0
    watch(testRef, () => {
      test2 = 1
    }, { flush: 'sync' })
    testRef.value = 1
    // eslint-disable-next-line no-console
    console.log(testRef, test2)
    return {
      test2
    }
  }
}
</script>

And run it in the ssr server environment

What is expected?

Both server returned result and client rendering should returns 1 because everything happened before returning from setup ().

Watch with flush: 'sync' should be respected as it don't use component live cycle

What is actually happening?

The server html returns 0.

Watch on ssr is ignored unconditionally

System Info

System:
    OS: Linux 5.4 Ubuntu 20.04.2 LTS (Focal Fossa)
    CPU: (8) x64 AMD Ryzen 9 5950X 16-Core Processor
    Memory: 1.01 GB / 15.64 GB
    Container: Yes
    Shell: 5.0.17 - /bin/bash
  Binaries:
    Node: 14.15.0 - ~/.nvm/versions/node/v14.15.0/bin/node
    Yarn: 1.22.10 - ~/.nvm/versions/node/v14.15.0/bin/yarn
    npm: 6.14.8 - ~/.nvm/versions/node/v14.15.0/bin/npm
  Browsers:
    Chrome: 92.0.4515.131
    Chromium: 101.0.4951.64
    Firefox: 90.0.2
    Firefox Nightly: 60.0a1

Any additional comments?

Context:

I am using pinia store in SSR (nuxts) and try to persist data to cookie with the $subscribe method of pinia store.

But the callback never runs even specify { flush: 'sync' }. So I always get empty cookie.

After a bit of trace, I found the $subscribe use watch to achieve the update notifying And vue ignored watch (even 'sync', which is completely unrelated to component live cycle) in ssr mode.