core
core copied to clipboard
`v-bind` not working with `computed` properties in SSR
Vue version
8edf4b3
Link to minimal reproduction
https://sfc.vuejs.org/#__SSR__eNp9kM1uhDAMhF/FyoVFWsgdAVJfoedcWOJtWZEf2YGqQrx7HaiqVSv1lhl7PnmyqZcY63VB1aiWR5piAsa0xN74ycVACTYYg4tLQgs73Ck4KGS/MN74MXhOMp4DQfezdrmU0PVQENqiNL7VJ1eIIhK6OA8JRQG0dlphnAfmzih5G3XYAK9oj7kWU6xWP8VEcvqcEXgMEa04dcZsOXCc0sBa3SZvL4cqM8/4/Tgk53p1VWe1yg2xfnDwUv6Im+8BG9WcwOxJ26yNek8pcqM138f8ZQ+uA71pedW0+DQ5rJFddaPwwUgCNur6xNBirkgVobdISP8xf63+4WasNNrV/gWkXprz
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/framework/issues/5546
@skirtles-code observed that it's not just computed, anything deemed setup-maybe-ref will fall into the same problem:
https://sfc.vuejs.org/#__SSR__eNp9UE1rhTAQ/CtLLio8zV1U6F/oqYdcfLq2PjQJu9FSxP/eTezh0UIPgczszOzHoV68r/YNVa0aHmj2ARjD5jtj59U7CnAA4QQnTORWyESaGWvs4CwH2BjfoIW8gLaLsjwjHLMCwNj4LtHgFkeiiuK8MLbRVyNpISDg6pc+oCCAZpx3GJaeuTVK/kYlGuAVx1TXQgrV6CebQA5fCwIPzuMoTBVjjmhIvWvYy/tsxzwhmS7OdqZBoq9TN3XtWq69rx7srFwj2c1PgY2qr8DIyQ0iNuojBM+11jwN8YYPrhy9a/lVtNkwr1ghr+Wd3CcjSbBRt6cMLeSOVBLaEQnpv8xf0j+5MVY2OtX5DXtJnx4=
weirdly, as in the JS tab of the playground, _unref seems to be imported ...
@LinusBorg Yeah, it is in the JS tab, but not in the SSR tab.
🤦🏻♂️thanks
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.
- bug was introduced after 3.2.26
- it only happens for me when I don't import
computedand use it. - logging
astbefore and after this transform call to check what the difference is, I found that theUNREFsymbol was missing from thehelpersproperty when I did not importcomputed - Looking even further I found the
UNREFhelper symbol was being added whencomputedwas imported during thistraverseNodecall.
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