-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
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
feat(hmr): reload for circular imports only if error #15118
Conversation
I'm working on a codebase (https://linear.app/) with many inherent circular dependencies that will take a lot of effort to remove. So I'm very curious about improving the HMR experience. @bluwy what is the status of this PR? Any downsides to this approach @patak-dev? |
We're discussing this one with the team. I'm good merging this one to try it out in the wild, and we can keep improving warning messages to guide users. I'd like @ArnaudBarre's opinion here, as he has been dealing with many issues due to circular imports and HMR. One option would be to offer this feature under a (experimental?) flag so we can get it out and test things out before deciding if this should be the default |
I think that would be a good start. I'm happy to provide feedback and test it out. |
What's the recommended way if I just want to test out this PR on our codebase? Do I need to use pnpm patch or is there a simpler way to do this? |
One way is to link vite, as described here. I like to use overrides, though. If you are using "pnpm": {
"overrides": {
"vite": "/path-to-vite-root/packages/vite"
}
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
I think HasDeadEnd
can be cleaned up
I think we could send back a message to the server saying that this file caused reload (like with invalidate) so that even without hmr debug on you can know the reason behind the full page reload
It's usually tricky to have the client send back to the server like that since you could have multiple clients connected at the same time. We could have the
I think we could fit this in 5.1 without an option. Without a page reload, it reverts to the Vite 4 behaviour so I think it's safe, but the catch handler would work additionally to detect circular fails and reloads instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess there are some false-positives/false-negatives with the way this PR detects whether a reload is needed or not. But I think the DX improvement justifies having them.
Because of the default of reload often clear logs, I think use console.log instead of debug is fine so people can quicly see it before the reload and enable "preserve logs" afterwards to read it. But maybe a lot of devs already uses "preserve logs" and it will be annoying |
I think most browsers will default to show debug logs, so it shouldn't get hidden in most case unless they explicitly hide it. The vite connection messages are also debug so currently leaning towards the consistency. |
At least for Chrome, |
FYI I tested this out. Didn't really see any improvement in our case, but also no regression. Which cases would a circular dependency be flagged but not fail the client? |
If you're accessing the exported names within a circular dependency loop on initialization, it could trigger an error. If they're lazily referenced, usually it will work. If you did hit the issue, perhaps you're seeing #3033. The fix for it (#13024) IMO wasn't safe, that a single module could have duplicated instances to workaround the issue. Today, that issue is fixed by triggering a full reload instead.
If y'all prefer a different kind of log, I don't mind changing it too 👍 Maybe |
I don't have a strong opinion but if I had to choose, I'll go with |
Is that possible to opt out of this behaviour? So page refresh is triggered when circular import detected. |
Is there a reason you want a page reload? HMR should kick in instead so you'd see the changes. If HMR didn't kick in and it didn't cause any errors for us to catch, then that would be a bug in the HMR implementation I think. |
HMR kicks in, I see updated version in the Network tab of the browser, logs in the console, but nothing changes until I force refresh the whole page. That happens only on a page with circular imports and inconsistent exports. So, if I export both MobX class and a component, it just reports error "hmr invalidate" to the console. So I believe it's expected behaviour. I had to downgrade to 5.0.12 to get rid of this. |
I think it would be best if you can open a new issue for it with a repro of the problem. Depending if this is used for react/vue/preact etc, it might be a Vite plugin specific issue. Otherwise I don't think there should be a way to opt of of this PR, there's a bigger problem if HMR fails this way. |
@AlexanderFarkas if u open a new issue, pls put it here.. i'm also facing this issue. |
I am working on reproduction sample, but no luck with if project is new. Once I manage to reproduce, I will create the issue. |
Description
Because people love circular imports.
This PR will not forcefully reload the page if a circular import is detected for the HMR boundary. Instead, it'll signal to the client to "watch out" for fails and if so, trigger a reload.
Currently it'll only "watch out" for fails when dynamically importing the new module, I think that's the only place we need to catch. Errors from HMR handlers don't need to be caught I think.
Additional context
What is the purpose of this pull request?
Before submitting the PR, please make sure you do the following
fixes #123
).