-
-
Notifications
You must be signed in to change notification settings - Fork 91
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
Comments
The process is definitely worth simplifying, maybe even fixed. Without the current implementation, there was no invalidation at all and things were even worse... |
Implementing the HMR using the instructions from the HMR page reloads the full page, but ignores the layout file. After HMR, the page just shows the content of the import { handleHotUpdate } from 'vue-router/auto-routes'
// TODO this is not working
if (import.meta.hot) {
handleHotUpdate(router)
} |
Same problem. Add the following code.
|
@jods4 Do you have small examples I can debug in the playground regarding this:
Regarding the suggestions, are you suggesting both things?
|
@cucuzi Can you try cloning the repository and reproducing the HMR error within the playground? ( |
Hi @posva ! I will try to reformulate the suggestions. There was basically 3 points in my issue.
Note Explanation/reprodution of one potential issue (it was a long time ago, keep in mind my memory could be fuzzy): If the Vue file you've modified is not loaded yet in client, then no HMR will take place.
|
For what it's worth, in my plugin config I added this piece of code in const module = server?.moduleGraph.getModuleById("/__vue-router/auto-routes");
if (module) server.reloadModule(module); It's a hack and triggers too much, but it helps until this issue gets fixed. |
Thanks for taking the time! I'm struggling to reproduce the duplication of auto-routes but I think I've seen it
Internally we do not rewrite the dts file but we do need to call the hooks in order to let users apply changes. So we can control that internally and I will play around with it to push changes forward. If that work, we shouldn't need an API like |
Here's a scenario from the applications I work on:
It would be nice to have an event to let us know the routes have changed and rebuild that table. Could we work around this without an event? But if you share that navigation across multiple components, it won't work. What do you think? EDIT: Honestly, if the route reloaded event is too annoying to add, don't bother. There are hacks around it and it has a limited (advanced) use. |
I'm considering adding an optional callback to |
I think it does. The routes will be available to callback? |
Good idea! They can be made available, they should also be accessible with |
yes: |
So something like this: import { createRouter, createWebHistory } from 'vue-router'
import { routes, handleHotUpdate } from 'vue-router/auto-routes'
export const router = createRouter({
history: createWebHistory(),
routes,
})
function addRedirects() {
router.addRoute({
path: '/new-about',
redirect: '/about?from=/new-about',
})
}
if (import.meta.hot) {
handleHotUpdate(router, (routes) => {
addRedirects()
})
} else {
// production
addRedirects()
} The callback would trigger after replacing routes by default. If needed, another syntax can be added |
@posva That would work for me |
I tested HMR more this time and things seem to be working well now! |
I think it's caused by import the 'vite-plugin-vue-layouts'. |
I updated the docs for runtime routes + HMR. Feel free to send a PR to improve! |
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: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:
extendRoutes
andbeforeWriteFiles
can do a lot of shenanigans that may have different dependencies and are basically impossible to predict.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
exportshandleHotUpdate(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 withhot.accept("/__vue-router/auto-route")
.The way to go is to subscribe to notifications with
import.meta.hot.on('vite:afterUpdate', args =>...)
and filterargs.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 callrouter.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 aonRouteUpdated(routes => ..)
function to register listeners that are called byaccept
?The text was updated successfully, but these errors were encountered: