`v-bind` not working with `computed` properties in SSR
Vue version
8edf4b3
Link to minimal reproduction
Steps to reproduce
Open link, make sure its on PROD with SSR ON. Near line 20 in SSR tab we have an _unref
call. But it isn't imported first.
What is expected?
For build to succeed. (_unref
to be imported from vue
prior to its call.)
What is actually happening?
ReferenceError: _unref
is not defined
System Info
No response
Any additional comments?
https://github.com/vuejs/vitepress/issues/876, https://github.com/nuxt/nuxt.js/issues/14203
@skirtles-code observed that it's not just computed
, anything deemed setup-maybe-ref
will fall into the same problem:
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 _unref
s 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.
- bug was introduced after 3.2.26
- it only happens for me when I don't import
computed
and use it. - logging
ast
before and after this transform call to check what the difference is, I found that theUNREF
symbol was missing from thehelpers
property when I did not importcomputed
- Looking even further I found the
UNREF
helper symbol was being added whencomputed
was imported during thistraverseNode
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.
PR for the fix: https://github.com/vuejs/core/pull/6489