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

HMR improvements #503

Open
jods4 opened this issue Sep 6, 2024 · 1 comment
Open

HMR improvements #503

jods4 opened this issue Sep 6, 2024 · 1 comment
Labels
⚡️ enhancement improvement over an existing feature

Comments

@jods4
Copy link

jods4 commented Sep 6, 2024

I would like to suggest a few improvements to HMR.

I observe updateRoutes is only invoked when adding or removing page.

In updatePage there's a comment:

// no need to manually trigger the update of vue-router/auto-routes because
// the change of the vue file will trigger HMR

That's not accurate.
Vite will notice the module has changed and invalidate it, but it will not actively push it through HMR to clients.
As auto-routes is typically not referenced by pages or components, only by the module that create routes, it might not be reloaded for a long time, if ever.
It also looks that this "late update" is not considered HMR and just creates duplicate modules in the front-end, which led me to all sorts of confusing issues.
I would suggest to trigger HMR when the routes are modified

Is this really the right place to do it though?
Consider:

  1. extendRoutes and beforeWriteFiles can do a lot of shenanigans that may have different dependencies and are basically impossible to predict.
  2. Updates trigger basically on every page edit. That's often , and most of the time no route-impacting change is actually made.

For these reasons I would suggest a different approach altogether: after the auto-routes virtual file has been rebuilt, compute a hash. If the hash is different from previous generation, send HMR. This covers all possible changes (add/remove/update/extensibility changes) and never sends unnecessary HMR to front-end.

Tip

Some tips for people googling how to update more than the router itself:
auto-route exports handleHotUpdate(router), which you can use to register your app router. With this, your router will automatically be updated whenever auto-routes is HMR. Very cool!
If you want to update more than the router, for example if your navigation menu is built off of your route table... it's possible but not obvious.
Because auto-routes self-accepts HMR, it won't propagate further: don't try to accept it with hot.accept("/__vue-router/auto-route").
The way to go is to subscribe to notifications with import.meta.hot.on('vite:afterUpdate', args =>...) and filter args.updates.some(u => u.acceptedPath === '/__vue-router/auto-routes')
Note that you will not find the new module in args and the self-accepting HMR does not update the existing exports, only the router.
So to get the updated routes, your only way is to get your router and call router.getRoutes().

@posva Maybe this process is worth simplifying?
The obvious idea (to me) is a custom message hot.on('auto-routes:afterUpdate', routes => ..) but the bummer is that these messages can only be sent by server.
Alternatively auto-routes could export a onRouteUpdated(routes => ..) function to register listeners that are called by accept?

@posva posva added the ⚡️ enhancement improvement over an existing feature label Sep 7, 2024
@posva
Copy link
Owner

posva commented Sep 7, 2024

The process is definitely worth simplifying, maybe even fixed. Without the current implementation, there was no invalidation at all and things were even worse...
The info you provided here is really helpful, thank you. I will definitely take a look

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⚡️ enhancement improvement over an existing feature
Projects
Status: 📋 Backlog
Development

No branches or pull requests

2 participants