Vite-plugin-ssr doesn't have a built-in redirect mechanism, but it provides enough control: we can implement URL redirections ourselves.
URL redirections (aka "page redirections") are commonly used to protect private pages by redirecting unauthenticated users (e.g. from /admin
to /login
).
With vite-plugin-ssr, we can use a Route Function instead of doing such URL redirection, see Authentication.
For other use cases, we can implement redirections on the server-side (see Server-side) as well as on the client-side (see Client-side).
A frequent problem with client-side redirections are hydration mismatches, see Hydration Mismatch.
Instead of using URL redirections to protect private pages from unauthenticated users, we can use a Route Function to show a different page depending on whether the user is logged-in or not:
// /pages/login.page.route.js
// Route Function to render the login page to non-authenticated users, regardless of the URL.
export default pageContext => {
// Only render the login page to non-authenticated users
if (userIsLoggedIn(pageContext)) {
return false
}
return {
// We use a high precedence number of `99` to override all other routes.
// This means that non-authenticated users always see the login page,
// regardless of the URL.
precedence: 99
}
}
function userIsLoggedIn(pageContext) {
return pageContext.user !== null
}
See Routing > Routing Precedence.
After the user successfully logs in, we reload the page with window.location.reload()
(Server Routing) or navigate(window.location.pathname)
(Client Routing).
This approach preserves the URL during the entire login flow:
/admin
and sees the Login Page. (URL is /admin
.)/admin
.)/admin
.)The original intention of the user is preserved and there is no need for some complex URL restoration mechanism.
Instead of using this approach, we can also use the more traditional approach of performing a page redirection. See sections below.
We can perform a URL redirection by using pageContext
:
// /renderer/_default.page.server.js
// Environment: Node.js
export function render() {
if (someCondition) {
return {
documentHtml: null,
pageContext: {
redirectTo: '/some/url'
}
}
}
// The usual stuff
// ...
}
// server.js
app.get('*', async (req, res, next) => {
const pageContextInit = { urlOriginal: req.url }
const pageContext = await renderPage(pageContextInit)
if (pageContext.redirectTo) {
res.redirect(307, '/movie/add')
} else if (!pageContext.httpResponse) {
return next()
} else {
const { body, statusCode, contentType } = pageContext.httpResponse
res.status(statusCode).type(contentType).send(body)
}
})
We can also trigger a page redirection from onBeforeRender()
:
// movie.page.route.js
export default "/star-wars/@movieId"
// movie.page.server.js
export { onBeforeRender }
async function onBeforeRender(pageContext) {
const movie = await fetchMovie(pageContext.routeParams.movieId)
// If the user goes to `/movie/42` but there is no movie with ID `42` then
// we redirect the user to `/movie/add` so he can add a new movie.
if (movie === null) {
return {
pageContext: {
redirectTo: '/movie/add'
}
}
}
}
// /renderer/_default.page.server.js
// Environment: Node.js
export { render }
function render(pageContext) {
const { redirectTo } = pageContext
if (redirectTo) {
return {
pageContext: {
redirectTo
}
}
}
// The usual stuff
// ...
}
Note that vite-plugin-ssr doesn't know anything about
pageContext.redirectTo
: it's a custompageContext
value.
If we use Client Routing, then we can also redirect on the client-side.
// /renderer/_default.page.server.js
// Environment: Node.js
// We make `pageContext.redirectTo` available to the browser for client-side redirection
export const passToClient = [/*...*/, 'redirectTo']
// /renderer/_default.page.client.js
// Environment: Browser
import { navigate } from "vite-plugin-ssr/client/router";
export function render(pageContext) {
const { redirectTo } = pageContext
if (redirectTo) {
navigate(redirectTo)
return
}
// The usual stuff
// ...
}
Note that vite-plugin-ssr doesn't know anything about
pageContext.redirectTo
: it's a custompageContext
value.
If we use Client Routing we may end up with a hydration mismatch.
To remove the hydration mismatch, we may need to redirect on both the client-side and server-side.
There are situations when server-side redirection is not an option and we can only redirect on the client-side. In such case we can suppress the hydration mismatch warning. Alternatively, we can also first hydrate the original page (before redirecting) and then redirect and render the new page.