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

fix(ssr): watchEffect onInvalidate runner initialization (close #3322) #3323

Merged
merged 7 commits into from
Mar 25, 2021

Conversation

tjk
Copy link
Contributor

@tjk tjk commented Feb 27, 2021

No description provided.

@HcySunYang
Copy link
Member

Hey, thank you for your PR, but I think there is a better way. In SSR, we do not need to initialize runner.options.onStop, just change a little bit:

  const onInvalidate: InvalidateCbRegistrator = (fn: () => void) => {
    cleanup = () => {
      callWithErrorHandling(fn, instance, ErrorCodes.WATCH_CLEANUP)
    }
    if (!(__NODE_JS__ && isInSSRComponentSetup)) {
      runner.options.onStop = cleanup
    }
  }

@HcySunYang
Copy link
Member

I rethink about that, the callback registered with onInvalidate will not be executed in SSR at all, so we only need to provide a NOOP instead of onInvalidate.

@tjk
Copy link
Contributor Author

tjk commented Feb 28, 2021

@HcySunYang thanks for the feedback, that actually makes sense! I'll do another pass. Do you have a suggestion for improving the test?

PS: Edited the patch (much better!)

} else {
watchEffect(onInvalidate => {
expect(() => onInvalidate(noop)).not.toThrow(ReferenceError)
done()
Copy link
Member

@LinusBorg LinusBorg Feb 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done will get called by the first watchEffect bootstrap/run, which is not the SSR one, so an error in the SSR one would not be part of the test anymore, I think?

Will think about how to do this with async/await.

Copy link
Contributor Author

@tjk tjk Feb 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming (and running the tests seems to validate) that setup gets called twice. The first time, instance is not set, so we just set instance. The second setup call with SSR triggers the watchEffect branch.

I could rewrite with promises but I think it would be a bit more verbose... is that preferred?

@HcySunYang
Copy link
Member

I think it would be better if we write test case in server-renderer, as a special case, although it is related to watch, but it is also related to the rendering behavior of SSR.

@tjk
Copy link
Contributor Author

tjk commented Mar 1, 2021

@HcySunYang thanks for that pointer... much better place for it! Let me know if anything else should be touched up.

@LinusBorg LinusBorg changed the title fix(ssr): watchEffect onInvalidate runner initialization (#3322) fix(ssr): watchEffect onInvalidate runner initialization (close #3322) Mar 1, 2021
@HcySunYang
Copy link
Member

@tjk , great work, thanks

@LinusBorg LinusBorg added ❗ p4-important Priority 4: this fixes bugs that violate documented behavior, or significantly improves perf. scope: ssr labels Mar 9, 2021
@yyx990803 yyx990803 merged commit e4b5fcc into vuejs:master Mar 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
❗ p4-important Priority 4: this fixes bugs that violate documented behavior, or significantly improves perf. scope: ssr
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SSR watchEffect onInvalidate issue (Cannot access 'runner' before initialization)
4 participants