Subscribe on changes!

watch-effect behaves differently with dev-server vs. production build.

avatar
Apr 12th 2022

Version

3.2.31

Reproduction link

github.com

Steps to reproduce

Run the minimal reproduction (main branch) twice: Once with the dev-server ( npm run serve) and once with a production build (npm run build).

(A) Setup:

  1. Navigate to the project in a browser.
  2. You will see three things: 2.1 The output of the variable isWorking being set to false. 2.2 A button titled "Set isWorking to true and change it back after 5 seconds". 2.3 A button titled "Trigger WatchEffect".
  3. Open the browser console.

(B) Click the buttons and observe the browser console for the first time:

  1. Click the left button. This will change isWorking to true for 5 seconds, and change it back afterwards.
  2. While isWorking is still true, click the right button now.
  3. This will trigger the following console.log: "[is-working-watch-effect@startWatchEffect@watchEffect][1] Is currently working"
  4. When isWorking is changing back to false, the following console.log will be triggered: "[is-working-watch-effect@startWatchEffect][2] Is not working anymore"

(C) Click the buttons and observe the browser console for the second time:

  1. Click the left button again.
  2. While isWorking is still true, click the right button now again.
  3. This will trigger the following console.log again: "[is-working-watch-effect@startWatchEffect@watchEffect][1] Is currently working"
  4. Point of divergence: 4.1 [DEV-SERVER] When isWorking is changing back to false, the following console.log will be triggered: "[is-working-watch-effect@startWatchEffect][2] Is not working anymore". This only happens on the DEV-SERVER-build. 4.2 [PRODUCTION BUILD] When isWorking is changing back to false, no further console.log will be printed. This will actually not work again until the page is refreshed.

What is expected?

  1. It is expected that a Dev-Server-build and a Production-build work the same way.

  2. It is expected that watchEffect works the same every time (both lines are printed, instead of just the first).

What is actually happening?

  1. The Dev-Server build always prints both lines for watchEffect. The Production-build only prints both lines for watchEffect once. After that it will always only ever print the first line.

  2. In the Production-build watchEffect is only printing both lines once (the first time).


I spent a lot of time debugging this. Here are a few additional notes:

(I admit that it might be considered weird to stop the watchEffect from within itself. For a particular feature (=waiting until saving is done in our application) this does seem to be a sensible implementation to me. Even if you might disagree that this is a sensible implementation, I'm sure you agree that this should behave the same in all cases.)

  • I recorded two videos of this behavior:

(A) This is a video from the Dev-Server. This is working as intended:

https://user-images.githubusercontent.com/7631673/163072529-e5e3f1a0-1997-4385-85aa-08193cb6dd04.mp4

(B) This is a video from the Production-Build. This is broken / inconsistent / not working as expected / intended:

https://user-images.githubusercontent.com/7631673/163072746-36fa2023-a4b6-4fe2-8972-38055c8dd4a4.mp4


Our biggest issue is that this discrepancy is undermining the trust that we have in Vue's reactivity. We have an application with ~50 Vuex stores, hundreds of components and lots and lots of reactivity.

There have been other weird reactivity issues since upgrading to the newest version. We haven't been able to reproduce those as concisely as this one yet.

It is obviously really really important for us that our developers can come across reactivity issues in their Dev-Server builds, before it's caught later on a Staging or Live build.

avatar
Apr 13th 2022

I appreciate the quick fix. It looks good, can't wait to test it out!

Is there any insight on why there would be a difference between a Dev-Server and a Production-build on this matter?

Again, we wouldn't have been able to catch this issue during development-time, and that is a bit concerning.

avatar
Apr 14th 2022

I wonder if this is related to this, or something like this: https://github.com/vuejs/core/issues/5655#issuecomment-1086613873

avatar
Dec 26th 2022

I have still the issue in v3.2.45. Confirmed in v3.2.31, upgraded to v3.2.45 and the bug is still present.

avatar
Jan 6th 2023

Can confirm, but is there on 3.2.45

avatar
Feb 10th 2023

I'm seeing the exact same issue with watch() on 3.2.45 as does @mStirner , can someone reopen this please. @yyx990803 ?