-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
store logic is not reactive in data prefetching steps while doing ssr #877
Comments
Hi, and thanks for this! Can you point me to the test(s) that are failing as I can't run them currently? So I can take a look to better understand the implicatons right now? |
Here i pasted the output for you (github does not support collapsing of blocks, right?...)
|
A simple example for you about the implications: And have a store (pseudocode) like this: state: {
sandwiches: [],
selectedSandwich: ''
},
getters: {
availableSandwiches () { return filter(getters.allSandwiches)},
allSandwiches() {return state.sandwiches}
},
mutations: {
selectSandwich () { state.selectedSandwich = sandwich},
importSandwiches () { state.sandwiches = sandwiches}
},
actions: {
loadSandwiches(preselectSandwich) {
if (getters.allSandwiches.length) {
sandwiches = await fetchSandwiches()
mutations.importSandwiches(sandwiches)
}
if (preselectSandwich in getters.availableSandwiches) {
selectSandwich(preselectSandwich)
}
}
}
Vues SSR function will render a webpage with the sandwiches but without the preselection. The initial render of vue during $mount will match it because the sandwich ist not preselected in the store. Depending on your other data prefetching logic the website may flicker and select the sandwich afterwards because the browser tries to refetch the sandwiches (notices it already has some and skip that) but will preselect the Sandwich because now the getters are reactive. In most cases the bug does not lead to crashes (had some but got workarounds working) because the initial rendering matches. But afterwards you may get a crappy user experience. |
I think the best solution would be to create the computed properties of the getters with option Here: https://github.com/vuejs/vuex/blob/dev/src/store.js#L216 something like: computed[key] = () => ({
handler() { fn(store) },
lazy: !(process.env.VUE_ENV === 'server')
}) Maybe add an option to enable / disable this during |
Will see if I can come up with a PR tonight. |
Hey, so I was looking into this - the problem is that computed props are hardcoded to be lazy in Vue: https://github.com/vuejs/vue/blob/dev/src/core/instance/state.js#L167 @yyx990803 : If we intend to fix this vuex problem by making getters non-lazy during SSR, this means we have to change something in Vue first - right? |
I've incorporated the SSR env tests in 9438bab - note these tests will currently fail until Vue core's next patch release. |
thanks! this will mean a lot for our user experience |
Is there a workaround to get this working? |
@amritk this is already out in Vue 2.4.4. |
@yyx990803 that is very strange, I'm still seeing the error on Vue 2.4.4, Vuex 2.4.1, and Vue-server-renderer 2.4.4
Whereas this code works fine
|
@amritk then you should open a separate issue with a proper reproduction |
Ah kk, sorry thought it was the same issue |
Version
2.3.0
Reproduction link
https://github.com/Harper04/vuex/tree/bug/ssr
Steps to reproduce
Either:
Clone the linked repo and run
npm i && npm run test:ssr
Or:
Run tests in your own repo with (this mimics the environment vue sees during ssr rendering):
VUE_ENV=server npm run test:unit
Or:
Have a project with a lot of stores and watch for weird ssr behavior
What is expected?
The tests should run.
Your store logic should behave exactly the same no matter whether you run it in your browser or during an ssr data prefetching step.
What is actually happening?
Vue turns of reactivity in case of server side rendering the moment you create/import the an vue ssr renderer. For frontend components/real rendering this is perfectly okay and an important optimization.
The problem is that vuex also uses a vue instance internally in order to get the reactivity and caching for getters etc. Therefore also the reactivity of vuex is turned of during ssr. Every getter will return whatever it returned the first time it was called (think of isValid getters or filtered lists)
Debugging:
I did run the tests and my project with a modified version of vue where the
isServerRendering
check in theobserver
part of Vue is deactivated which worked fine.I also tried to just return the getter function instead of the computed property in mappedGetters (vuex) which also worked for me (but not for the tests).
PR?
I've tried to come up with a pull request where vue would get another constructor variable like
forceReactivity
ordataOnlyVueInstance
which vuex could pass in during instantiation.Unfortunately apart from hacks i could only think of solutions which meant to much work for the risk of solving it in a way you would not accept.
If you could show me a way to pass vm.$options parameters to the observer module without touching too much code i would still be happy to do a PR.
Am i right here?
This seems like a bug for vuex which should be solved by enhancing vue itself. Should i create a feature request there?
The text was updated successfully, but these errors were encountered: