Skip to content

watch() does not work after building for production using npm run build #7688

Closed
@olfek

Description

@olfek

Vue version

3.2.45

Link to minimal reproduction

will add zip file to this issue

Steps to reproduce

  1. Run npm run dev
  2. Observe that watch is called
  3. Run npm run build and serve using npx http-server dist
  4. Observe that watch is not called

What is expected?

watch callback gets called

What is actually happening?

watch callback does not get called

System Info

No response

Any additional comments?

creating this issue to bring attention back to (#5707)

looks like the bug affects both watch() and watchEffect()

Activity

olfek

olfek commented on Feb 10, 2023

@olfek
Author

Creating the minimal reproduction, I've learned that it has something to do with:

  • <Suspense> in App.vue
  • The use of await in HomeView.vue
olfek

olfek commented on Feb 10, 2023

@olfek
Author
olfek

olfek commented on Feb 10, 2023

@olfek
Author
  • Replacing await with void in HomeView.vue makes the problem go away.
  • <Suspense> was added in App.vue because without it, the use of await in HomeView.vue gives errors.
LinusBorg

LinusBorg commented on Feb 10, 2023

@LinusBorg
Member

This seems to be unrelated to #5707.

The problem here is that the component's props object is not being properly updated when the route changes - so the watch of course can't run, as props didn't change.

Here's what I could find out quickly:

The renderer triggers a re-render of the HomeView component, because in the component's vnode, the prop has been updated. However the propsobject in the component itself has not been updated with that new value, and so the watch is never triggered.

Addign this to HomeView:

onBeforeUpdate(() => {
        const vnodeProps = getCurrentInstance()?.vnode.props
        console.log('updating...', { ...props }, { ...vnodeProps })
    })

results in this console entry:

Bildschirm­foto 2023-02-10 um 22 40 46

So, seems to be a problem with Suspense, maybe in combination with <RouterView>.

/cc @posva does this look familiar to some problem you have seen before?

LinusBorg

LinusBorg commented on Feb 10, 2023

@LinusBorg
Member

Bildschirm­foto 2023-02-10 um 23 00 11

patchFlag is 0, so it should receive a full props diff, but optimized is true, so line 3823 evaluates to true, so the code enters that branch - where it then does nothing because patchFlag is 0(see line 3825).

That only happens when HomeView is async. When that component is not async, optimized is false, and thus a full props patch is being done, so the app works as expected in that case.

olfek

olfek commented on Feb 10, 2023

@olfek
Author

Have you been able to reproduce it @LinusBorg ? Is this now a confirmed bug?

LinusBorg

LinusBorg commented on Feb 10, 2023

@LinusBorg
Member

Yes

posva

posva commented on Feb 11, 2023

@posva
Member

There are other bugs with Suspense and keep alive that appear because the entering component renders before the leaving component. There are some open issues in vue router about this. But I don't recall any problem with a different behavior between dev and prod

LinusBorg

LinusBorg commented on Feb 11, 2023

@LinusBorg
Member

Got it. when calling suspense.registerDep, we don't pass the current value of optimize. Instead, in registerDep, we use the closure's value of optimized that was passed to createSusenseBoundary()

parentSuspense && parentSuspense.registerDep(instance, setupRenderEffect)

I think we would need to change registerDep to accept the optimized flag as a third argument?

registerDep(instance, setupRenderEffect, optimized = false) {

Not sure how to write a proper test for this though.

removed
securityPull requests that address a security vulnerability
on Feb 11, 2023
olfek

olfek commented on Feb 11, 2023

@olfek
Author

Thank you for triaging this and finding a fix so quickly, much appreciated @LinusBorg ❤️

olfek

olfek commented on Feb 11, 2023

@olfek
Author

The difference of behavior between dev and production is caused by the optimized parameter? @LinusBorg

LinusBorg

LinusBorg commented on Feb 11, 2023

@LinusBorg
Member

yes

added a commit that references this issue on May 31, 2024
c521f95
locked and limited conversation to collaborators on Jun 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @posva@LinusBorg@olfek

      Issue actions

        `watch()` does not work after building for production using `npm run build` · Issue #7688 · vuejs/core