-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Feature request
What problem does this feature solve?
Sometimes, we need to redirect to another location before the page finishes rendering. For example, in the following snippet,
vuepress/packages/@vuepress/core/lib/app/redirect.js
Lines 23 to 50 in 1850be7
| export function handleRedirectForCleanUrls (router) { | |
| router.beforeEach((to, from, next) => { | |
| if (isRouteExists(router, to.path)) { | |
| next() | |
| } else { | |
| if (!/(\/|\.html)$/.test(to.path)) { | |
| const endingSlashUrl = to.path + '/' | |
| const endingHtmlUrl = to.path + '.html' | |
| if (isRouteExists(router, endingHtmlUrl)) { | |
| next(endingHtmlUrl) | |
| } else if (isRouteExists(router, endingSlashUrl)) { | |
| next(endingSlashUrl) | |
| } else { | |
| next() | |
| } | |
| } else if (/\/$/.test(to.path)) { | |
| const endingHtmlUrl = to.path.replace(/\/$/, '') + '.html' | |
| if (isRouteExists(router, endingHtmlUrl)) { | |
| next(endingHtmlUrl) | |
| } else { | |
| next() | |
| } | |
| } else { | |
| next() | |
| } | |
| } | |
| }) | |
| } |
VuePress will try to redirect unknown request /foo to /foo.html and /foo/. Other scenarios include redirecting / to /zh/ or /en/ based on navigator language.
The snippet referenced above will work fine for most of the conditions. But if the page needs redirecting before rendering starts, uses server-side rendering and the pages before and after redirecting do not share an identical structure, this will lead to the problem called SSR Mismatch.
An example of handleRedirectForCleanUrls to explain the mismatch
You request
/fooin the browser, but the server can't find a direct match (without certain config), so a NotFound page/404.htmlwill be returned. ThebeforeEachhook registered inhandleRedirectForCleanUrlswill redirect the router to/foo.html. Note that the DOM remains unchanged but the VDOM is replaced with/foo.html's. Normally,/404.htmlis a plain page without navbar and sidebar, but the new VDOM is a document page with such components. The DOM fails to match the VDOM, causing rendering error and the view will not be updated. This is an SSR Mismatch and its consequence.
Summarize the bug-like problem as follow.
-
The server-side rendered pages need a
hydrationstage to be fully functional and thehydrationstage needs corresponding DOM and VDOM structure (a correctly server-side rendered website could easily achieve this). -
But, when at least one of DOM and VDOM changes before
hydration, DOM and VDOM mismatch will happen, especially in production distribution ofVuewhere the mismatch warning is indirect and there-renderingfallback is removed (see this issue in theVuerepository). -
Redirecting may be the most reasonable way for such condition to happen as the VDOM is changed and the pages before and after redirecting do not have identical VDOM structure.
The feature request aims to solve this problem.
What does the proposed API look like?
What I propose here is that VuePress should handle the problem internally for end users and plugin developers, for example, by postponing the redirection.
If it can't be solved gracefully, at least, the document should explicitly point this caveat out.
How should this be implemented in your opinion?
I mentioned bug-like above because I know it is not a bug of Vue Server Renderer or Vue Router. Instead, it should be addressed by the app itself. But developers may easily ignore this and waste much time debugging because the bug only exists in build mode with server-side rendering enabled. Even VuePress' official code (the snippet referenced above) has such problem as well.
Are you willing to work on this yourself?
I'm willing to participate in. Actually, I have experimented for a while but can't solve the problem without glitch. So, I post it out and seek help.