Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v-bind css variable crashes during ssr dev #6926

Closed
Trinovantes opened this issue Oct 22, 2022 · 5 comments · Fixed by #6979
Closed

v-bind css variable crashes during ssr dev #6926

Trinovantes opened this issue Oct 22, 2022 · 5 comments · Fixed by #6979
Assignees
Labels
❗ p4-important Priority 4: this fixes bugs that violate documented behavior, or significantly improves perf. has PR A pull request has already been submitted to solve the issue 🐞 bug Something isn't working scope: script-setup scope: ssr

Comments

@Trinovantes
Copy link

Vue version

3.2.41

Link to minimal reproduction

https://github.com/Trinovantes/vue-ssr-css-bind

Steps to reproduce

yarn install
yarn webpack
yarn watch

Visit localhost:8080 and server crashes with

[Vue warn]: Unhandled error during execution of watcher callback 
  at <App>
[Vue warn]: Unhandled error during execution of setup function 
  at <App>
ReferenceError: Cannot access 'paddingTop' before initialization
    at /home/stephen/Projects/vue-ssr-css-bind/dist/server.js:14760:73
    at setVars (/home/stephen/Projects/vue-ssr-css-bind/dist/server.js:12565:58)
    at callWithErrorHandling (/home/stephen/Projects/vue-ssr-css-bind/dist/server.js:6047:18)
    at callWithAsyncErrorHandling (/home/stephen/Projects/vue-ssr-css-bind/dist/server.js:6055:17)
    at getter (/home/stephen/Projects/vue-ssr-css-bind/dist/server.js:7266:16)
    at doWatch (/home/stephen/Projects/vue-ssr-css-bind/dist/server.js:7286:7)
    at watchPostEffect (/home/stephen/Projects/vue-ssr-css-bind/dist/server.js:7207:10)
    at useCssVars (/home/stephen/Projects/vue-ssr-css-bind/dist/server.js:12566:69)
    at setup (/home/stephen/Projects/vue-ssr-css-bind/dist/server.js:14759:52)
    at callWithErrorHandling (/home/stephen/Projects/vue-ssr-css-bind/dist/server.js:6047:18)

What is expected?

No crash

What is actually happening?

The generated setup function seems to be referencing paddingTop variable before it is declared

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
  __name: "App",
  setup(__props, { expose }) {
    expose();
    (0,vue__WEBPACK_IMPORTED_MODULE_0__.useCssVars)((_ctx) => ({
      "7ba5bd90-paddingTop": (0,vue__WEBPACK_IMPORTED_MODULE_0__.unref)(paddingTop)
    }));
    const paddingTop = (0,vue__WEBPACK_IMPORTED_MODULE_0__.computed)(() => "100px");
    const __returned__ = { paddingTop, computed: vue__WEBPACK_IMPORTED_MODULE_0__.computed };
    Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
    return __returned__;
  }
});

System Info

System:
    OS: Linux 5.10 Ubuntu 20.04.5 LTS (Focal Fossa)
    CPU: (12) x64 AMD Ryzen 5 2600 Six-Core Processor
    Memory: 12.60 GB / 15.60 GB
    Container: Yes
    Shell: 5.0.17 - /bin/bash
  Binaries:
    Node: 16.15.0 - /usr/local/bin/node
    Yarn: 1.22.19 - ~/.yarn/bin/yarn
    npm: 8.17.0 - /usr/local/bin/npm
  npmPackages:
    vue: ^3.2.41 => 3.2.41

Any additional comments?

Works fine without SSR

Workaround:

<h1 :style="{paddingTop}"> in the <template> instead but this is pretty cumbersome

@edison1105 edison1105 added 🐞 bug Something isn't working scope: ssr and removed 🐞 bug Something isn't working scope: ssr labels Oct 22, 2022
@edison1105
Copy link
Member

edison1105 commented Oct 27, 2022

We do not inject useCssVars in SSR mode. This seems related to vue-loader.
The inlineTemplate is always false passed from vue-loader in DEV mode.

// 8. inject `useCssVars` calls
if (
cssVars.length &&
// no need to do this when targeting SSR
!(options.inlineTemplate && options.templateOptions?.ssr)
) {
helperImports.add(CSS_VARS_HELPER)
helperImports.add('unref')
s.prependRight(
startOffset,
`\n${genCssVarsCode(cssVars, bindingMetadata, scopeId, isProd)}\n`
)
}

@earlAchromatic
Copy link

@edison1105 There are some use cases where it would actually be nice to have css vars work with SSR. For instance, if I am prerendering and then want to lazily hydrate some components but still have the css vars initially bound so styles show up. Not sure how Astro is doing this but my guess is you can't use css vars unless you are eventually CSR which is limiting.

Now Vue is often being used as an SSR templating language where people may want to use props to set css dynamically during the build but may never hydrate that component. I didn't see much other related discussion so thought I would chime in here. Happy to make a separate issue.

@edison1105
Copy link
Member

@earlAchromatic

For instance, if I am prerendering and then want to lazily hydrate some components but still have the css vars initially bound so styles show up.

Lazily hydrate is not supported by vue-core, Maybe you have to wait until Q2. The final implementation is uncertain and may not be the same as Astro. Now, CSS vars in SSR do not need hydrate because the initial value of CSS var is calculated in the SSR render phase.

people may want to use props to set css dynamically during the build but may never hydrate that component.

It will have to wait until vue implements lazily hydrate to see if there is a similar problem. If you already have this problem now, please open issues if you encounter them and talk about them more.

@haoqunjiang haoqunjiang changed the title v-bind css variable crashes during ssr v-bind css variable crashes during ssr dev Mar 24, 2023
@haoqunjiang haoqunjiang added has PR A pull request has already been submitted to solve the issue ❗ p4-important Priority 4: this fixes bugs that violate documented behavior, or significantly improves perf. labels Mar 24, 2023
@Lyokolux
Copy link

FYI this bug is currently happening in vue 3.2.47. I am simply running the vite --host command.

Given the shortened following component:

<template>
    <Icon :icon="icon" />
</template>

<script setup lang="ts">
import { computed, toRefs } from 'vue'

const props = defineProps<{
  state: 'pending' | 'running' | 'completed' | 'failed'
}>()

const { bgColor, color, icon } = toRefs(useStatusDisplay(state))
</script>

<style scoped lang="scss">
.run-status :deep(i) {
  color: v-bind(color);
}
</style>

it outputs

setup(__props, { expose }) {
    expose();
    const props = __props;
    _useCssVars((_ctx) => ({
      "1c89043a-color": _unref(color)
    }));
    const { bgColor, color, icon } = toRefs(useStatusDisplay(state));
}

with the error: Uncaught (in promise) ReferenceError: Unhandled Promise Rejection: can't access lexical declaration 'color' before initialization

@edison1105
Copy link
Member

@Lyokolux
It can work normally because this code will run after mounting.

(_ctx) => ({
	"1c89043a-color": _unref(color)
})

it works fine see demo
Would you mind provide a runnable mimimal reproduction?

@github-actions github-actions bot locked and limited conversation to collaborators Nov 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
❗ p4-important Priority 4: this fixes bugs that violate documented behavior, or significantly improves perf. has PR A pull request has already been submitted to solve the issue 🐞 bug Something isn't working scope: script-setup scope: ssr
Projects
None yet
5 participants