Subscribe on changes!

`v-bind` not working with `computed` properties in SSR

avatar
Jun 29th 2022

weirdly, as in the JS tab of the playground, _unref seems to be imported ...

avatar
Jun 29th 2022

@LinusBorg Yeah, it is in the JS tab, but not in the SSR tab.

avatar
Jun 29th 2022

🤦🏻‍♂️thanks

avatar
Aug 1st 2022

I have been experiencing a similar issue on v3.2.37. I am using vite & vite-ssr. The issue seems a bit different for me however.

I have a component that looks like this
<script lang="ts">
import { provideTheme } from '@social/client/themes'
import globalTheme from '@social/client/themes/global'
import { defineComponent } from 'vue'

export default defineComponent({
    name: 'NoLayoutLayout',
})
</script>

<script lang="ts" setup>
const theme = provideTheme(globalTheme)
</script>

<template>
    <RouterView class="no-layout" />
</template>

<style lang="scss" scoped>
.no-layout {
    background-color: v-bind('theme.color.secondary');
    color: v-bind('theme.color.secondaryText');

    font-family: v-bind('theme.font.body');
    font-weight: v-bind('theme.font.bodyWeight');
}

:deep(h1, h2, h3, h4, h5, h6) {
    padding: 0.5em 0px;
    margin: 0px;
    color: v-bind('theme.color.secondaryText');
    font-family: v-bind('theme.font.header');
    font-weight: v-bind('theme.font.headerWeight');
}

:deep(img) {
    max-width: 100%;
    max-height: 100%;
    object-fit: cover;
}

:deep(a) {
    color: inherit;
}
</style>

During dev, works just fine. Once built and running in prod, we get the _unref is not defined error.

If I import `computed` and actually use it like this
<script lang="ts">
import { provideTheme } from '@social/client/themes'
import globalTheme from '@social/client/themes/global'
import { defineComponent, computed } from 'vue'

export default defineComponent({
    name: 'NoLayoutLayout',
})
</script>

<script lang="ts" setup>
const test = computed(() => false)
const theme = provideTheme(globalTheme)
</script>

<template>
        <div v-if="test">test</div>
    <RouterView class="no-layout" />
</template>

<style lang="scss" scoped>
.no-layout {
    background-color: v-bind('theme.color.secondary');
    color: v-bind('theme.color.secondaryText');

    font-family: v-bind('theme.font.body');
    font-weight: v-bind('theme.font.bodyWeight');
}

:deep(h1, h2, h3, h4, h5, h6) {
    padding: 0.5em 0px;
    margin: 0px;
    color: v-bind('theme.color.secondaryText');
    font-family: v-bind('theme.font.header');
    font-weight: v-bind('theme.font.headerWeight');
}

:deep(img) {
    max-width: 100%;
    max-height: 100%;
    object-fit: cover;
}

:deep(a) {
    color: inherit;
}
</style>

Then once built, the previously _unrefs are transformed into vue.unref, which is correct and makes the app work again.

Now, this is the first time really diving into the vue core, so I might have been looking at the wrong thing, but I did some digging and found a couple things.

  1. bug was introduced after 3.2.26
  2. it only happens for me when I don't import computed and use it.
  3. logging ast before and after this transform call to check what the difference is, I found that the UNREF symbol was missing from the helpers property when I did not import computed
  4. Looking even further I found the UNREF helper symbol was being added when computed was imported during this traverseNode call.

This is as far as I got for my case. I look into the traverseNode code, but couldn't find anything glaring at me that could be causing it. It does loop thru the transformNodes tho, so I am going to assume something is going wrong within those calls.

Looking at the possible transformers being run, the only one that caught my eye was ssrInjectCssVars, but again I am not currently seeing anything glaring at me that could be wrong.

avatar
Aug 29th 2022